Введение
В современной Android-разработке использование Jetpack Compose для создания UI, наряду с надежными сетевыми библиотеками, такими как Retrofit и Ktor, и фреймворком для внедрения зависимостей, таким как Dagger Hilt, формирует масштабируемую и поддерживаемую архитектуру. Это руководство поможет настроить простое Android-приложение для отображения списка автомобилей с использованием сетевых библиотек (сначала Retrofit, затем Ktor), интегрированных с Dagger Hilt для внедрения зависимостей.
Jetpack Compose, Dagger Hilt, Retrofit, Ktor: общие сведения
Jetpack Compose
Jetpack Compose — современный Android-инструментарий для разработки нативных пользовательских интерфейсов. Он использует декларативный подход, позволяя разработчикам создавать сложные интерфейсы с меньшим количеством кода и большей гибкостью по сравнению с традиционным UI-фреймворком на основе XML.
Dagger Hilt
Dagger Hilt — библиотека внедрения зависимостей для Android, которая упрощает настройку Dagger. Она автоматизирует большую часть шаблонного кода и позволяет устанавливать зависимости в Android-компонентах проще и удобнее.
Retrofit
Retrofit — типизированный HTTP-клиент для Android и Java, созданный на базе OkHttp. Он абстрагирует процесс выполнения сетевых запросов и парсинга ответов, упрощая работу с REST API.
Ktor
Ktor — фреймворк для создания асинхронных серверов и клиентов в связанных системах с использованием Kotlin. Гибкий и настраиваемый HTTP-клиент, который предоставляет Ktor, можно применять в Android-приложениях в качестве альтернативы Retrofit.
1. Отображение списка автомобилей с помощью Retrofit
Шаг 1: Настройка Retrofit
Для начала настройте Retrofit в своем проекте для получения данных из сетевого источника.
Добавление зависимостей
В build.gradle
(на уровне приложения) включите следующие зависимости:
dependencies {
implementation "com.squareup.retrofit2:retrofit:<latest-version>"
implementation "com.squareup.retrofit2:converter-gson:<latest-version>"
implementation "com.squareup.okhttp3:okhttp:<latest-version>"
implementation "com.squareup.okhttp3:logging-interceptor:<latest-version>"
implementation "androidx.compose.ui:ui:<latest-version>"
implementation "androidx.compose.material:material:<latest-version>"
implementation "androidx.compose.ui:ui-tooling-preview:<latest-version>"
implementation "androidx.hilt:hilt-navigation-compose:<latest-version>"
}
Создание модели данных
Определите класс данных, представляющий модель автомобиля:
data class Car(
val id: Int,
val name: String,
val manufacturer: String
)
Создание интерфейса API Retrofit
Определите интерфейс, который Retrofit будет использовать для получения списка автомобилей:
interface CarApiService {
@GET("cars")
suspend fun getCars(): List<Car>
}
Создание модуля Retrofit с помощью Dagger Hilt
Создайте модуль Dagger Hilt, который будет предоставлять экземпляры Retrofit и OkHttp:
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
@Singleton
fun provideOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
})
.build()
}
@Provides
@Singleton
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
return Retrofit.Builder()
.baseUrl("https://api.example.com/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
@Provides
@Singleton
fun provideCarApiService(retrofit: Retrofit): CarApiService {
return retrofit.create(CarApiService::class.java)
}
}
Шаг 2: Получение данных в ViewModel
Создайте ViewModel для управления получением и хранением списка автомобилей:
@HiltViewModel
class CarViewModel @Inject constructor(
private val carApiService: CarApiService
) : ViewModel() {
private val _cars = mutableStateOf<List<Car>>(emptyList())
val cars: State<List<Car>> = _cars
init {
fetchCars()
}
private fun fetchCars() {
viewModelScope.launch {
_cars.value = carApiService.getCars()
}
}
}
Детали
- ApiService Retrofit: вызов
carApiService.getCars()
в ViewModel использует экземпляр созданного Retrofit интерфейсаCarApiService
. Retrofit динамически генерирует реализацию этого интерфейса, что позволяет легко определять и использовать конечные точки API безопасным для типов образом.
- Интеграция с OkHttp: Retrofit полагается на OkHttp в качестве базового HTTP-клиента.
OkHttpClient
настраивается и предоставляется для Retrofit вNetworkModule
, что позволяет настраивать поведение сети: логирование, таймауты и перехватчики. OkHttp обрабатывает низкоуровневые детали выполнения HTTP-запросов и управления соединениями.
- Конвертер Gson: Retrofit использует фабрику конвертеров, например
GsonConverterFactory
, для автоматической сериализации и десериализации JSON, что позволяет Retrofit конвертировать JSON-ответы от API непосредственно в объекты данных Kotlin (например,Car
) с минимальными настройками, упрощая процесс работы с ответами API.
Шаг 3: Отображение списка автомобилей с помощью LazyColumn
Теперь можно отобразить список автомобилей с помощью LazyColumn
в Jetpack Compose:
@Composable
fun CarListScreen(viewModel: CarViewModel = hiltViewModel()) {
val cars by viewModel.cars
LazyColumn {
items(cars) { car ->
CarItem(car)
}
}
}
@Composable
fun CarItem(car: Car) {
Card(modifier = Modifier.padding(8.dp).fillMaxWidth()) {
Column(modifier = Modifier.padding(16.dp)) {
Text(text = car.name, style = MaterialTheme.typography.h6)
Text(text = car.manufacturer, style = MaterialTheme.typography.body2)
}
}
}
Шаг 4: Интеграция в MainActivity
Наконец, интегрируйте CarListScreen
в класс MainActivity:
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
CarListScreen()
}
}
}
2. Отображение списка автомобилей с помощью Ktor
Теперь реализуем ту же функциональность, используя Ktor вместо Retrofit.
Шаг 1: Настройка Ktor
Добавление зависимости
Замените зависимости Retrofit на зависимости Ktor в файле build.gradle
:
dependencies {
implementation "io.ktor:ktor-client-core:<latest-version>"
implementation "io.ktor:ktor-client-cio:<latest-version>"
implementation "io.ktor:ktor-client-serialization:<latest-version>"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:<latest-version>"
}
Создание модуля клиента Ktor
Создайте модуль Dagger Hilt для предоставления HttpClient
Ktor:
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
@Singleton
fun provideHttpClient(): HttpClient {
return HttpClient(CIO) {
install(JsonFeature) {
serializer = KotlinxSerializer()
}
}
}
}
Шаг 2: Получение данных во ViewModel с помощью Ktor
Обновите ViewModel, чтобы использовать HttpClient
Ktor для получения данных:
@HiltViewModel
class CarViewModel @Inject constructor(
private val client: HttpClient
) : ViewModel() {
private val _cars = mutableStateOf<List<Car>>(emptyList())
val cars: State<List<Car>> = _cars
init {
fetchCars()
}
private fun fetchCars() {
viewModelScope.launch {
try {
_cars.value = client.get("https://api.example.com/cars")
} catch (e: Exception) {
_cars.value = emptyList()
}
}
}
}
Детали
-
HttpClient
Ktor:client
в вызовеclient.get("https://api.example.com/cars")
является экземпляромHttpClient
Ktor, а не OkHttp. КлассHttpClient
является частью фреймворка Ktor и предназначен для обработки асинхронных сетевых операций.
- Движок CIO: в модуле
NetworkModule
HttpClient
настроен на использование движка CIO, который является стандартным движком ввода/вывода Ktor, основанным на корутинах — этот механизм обрабатывает HTTP-запросы и ответы.
- Сериализация:
KotlinxSerializer
используется вместе сJsonFeature
для обработки сериализации и десериализации JSON, что позволяет автоматически преобразовывать ответы в объекты Kotlin.
Шаг 3: Отображение списка автомобилей с помощью LazyColumn
Можете повторно использовать те же composable-функции CarListScreen
и CarItem
, которые были определены ранее, поскольку пользовательский интерфейс остается неизменным:
@Composable
fun CarListScreen(viewModel: CarViewModel = hiltViewModel()) {
val cars by viewModel.cars
LazyColumn {
items(cars) { car ->
CarItem(car)
}
}
}
@Composable
fun CarItem(car: Car) {
Card(modifier = Modifier.padding(8.dp).fillMaxWidth()) {
Column(modifier = Modifier.padding(16.dp)) {
Text(text = car.name, style = MaterialTheme.typography.h6)
Text(text = car.manufacturer, style = MaterialTheme.typography.body2)
}
}
}
Шаг 4: Интеграция в MainActivity
Настройка класса MainActivity остается прежней:
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
CarListScreen()
}
}
}
Заключение
И Retrofit, и Ktor могут быть эффективно использованы для получения и отображения данных в Android-приложении с помощью Jetpack Compose и Dagger Hilt. Выбор между этими двумя библиотеками зависит от требований конкретного проекта.
- Retrofit: подойдет разработчикам, которым нужна хорошо зарекомендовавшая себя, простая в использовании библиотека с большим сообществом и встроенной интеграцией OkHttp.
- Ktor: предлагает больше гибкости и возможностей для настройки, что делает этот фреймворк идеальным выбором для проектов, требующих тонкого контроля над сетевыми операциями.
Следуя этому руководству, вы сможете реализовать простое отображение списка, используя как Retrofit, так и Ktor. Выбирайте тот вариант, который соответствует вашим потребностям.
Читайте также:
- Как создать анимацию кругового вытеснения в Jetpack Compose
- Как создать форму текстового фона в Jetpack Compose
- Новые способы оптимизации стабильности в Jetpack Compose
Читайте нас в Telegram, VK и Дзен
Перевод статьи Dobri Kostadinov: Jetpack Compose: Setup Retrofit and Ktor using Dagger Hilt for Dependency Injection