Lista de criptomonedas que usan bibliotecas Paging 3 y Jetpack Compose | Por Viktor Roslyakov | Febrero de 2022
Aquí hay una aplicación de muestra que demuestra Paginación 3 Bibliotecas y composición de mochila propulsoraLa aplicación se basa en el enfoque arquitectónico limpio de Uncle Bob.
También uso Kotlin (por supuesto), Flow, MVVM, Dagger Hilt.
Enlace del repositorio en github: https://github.com/mrvectorr/cryptopagingapp
de qué se trata la aplicación
Elegí uno de los temas más candentes en este momento. Mi aplicación muestra una lista de criptomonedas.como proveedor de precios de criptomonedas que uso mensajero de fuego.
Se parece a esto:
Configuración del proyecto
Agregue las dependencias necesarias para Redactar y Paginar construir.gradle documento.
dependencies {
...
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.paging:paging-compose:1.0.0-alpha14"
...
}
Dependencias para Dagger Hilt (Inyección de dependencia)
plugins {
...
id 'dagger.hilt.android.plugin'
}...
dependencies {
...
implementation "com.google.dagger:hilt-android:2.38.1"
kapt "com.google.dagger:hilt-android-compiler:2.37"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
kapt "androidx.hilt:hilt-compiler:1.0.0"
implementation 'androidx.hilt:hilt-navigation-compose:1.0.0'
...
}
Configure el archivo de aplicación para Hilt agregando HiltAndroidApp anotación
@HiltAndroidApp
class CryptoApplication : Application()
Descripción general de la arquitectura
Las aplicaciones se dividen en capas de datos, dominio y presentación. La idea principal de la arquitectura limpia es separar las preocupaciones manteniendo las reglas comerciales ignorantes del mundo exterior. Si no está familiarizado con este concepto, le recomiendo que profundice en él.
En esta sección, explicaré mi implementación de esta aplicación.
Empecemos con datos Piso. Utilizamos la actualización para cargar datos del servidor.esta es la funcion
@GET("api/v2/assets")
suspend fun getAssets(
@Query("page") page: String,
@Query("fields", encoded = true) fields: String,
@Query("limit") limit: String = "20"
): AssetsDto
vamos a pasar a Fuente de datos de activos. Esta clase es responsable de cargar los datos y almacenarlos en caché en variables. En la fuente de datos, solo tenemos una función que carga la siguiente página y la guarda en el caché.
override suspend fun getAssets(page: Int): Collection {
return if (assetsList.size % 20 == 0) {
if (page * 20 > assetsList.size) {
val currentPage = assetsList.size / 20 + 1
val assetsDto = api.getAssets(currentPage.toString(), Constants.GET_ASSETS_FIELDS)
(assetsList as MutableList).addAll(assetsDto.data)
assetsDto.data
} else {
val list = (assetsList as MutableList).slice((page - 1) * 20 until page * 20)
list
}
} else {
emptyList()
}
}
adquirir activos la funcion se llama ActivosRepositorioImpl clase. interfaz repositorio de activos está en el dominio. Este es el truco más importante sobre cómo ocultamos la implementación del repositorio de la capa de dominio.
existe campo tenemos capas Obtener fuente de activos La clase que reemplaza al interactor en nuestra arquitectura.
introducir Las capas son básicamente el patrón MVVM.
Además, explicaré la capa de presentación y la capa de dominio en detalle.
fuente de paginación
Deberíamos crear una subclase de la clase PagingSource para pasar datos a nuestra lista.Hay dos funciones que tenemos que anular
carga interesante (parámetros: PagingSource.LoadParams
y
interesante getRefreshKey (estado: PagingState
Toda la magia sucede en carga función, aquí llamamos a nuestra función getAssets repositorio de activos clase.
override suspend fun load(params: LoadParams): LoadResult {
val nextPage = params.key ?: 1
return try {
LoadResult.Page(
data = repository.getAssets(nextPage), prevKey =
if (nextPage == 1) null
else nextPage - 1,
nextKey = nextPage.plus(1)
)
} catch (e: HttpException) {
LoadResult.Error(Exception(e.localizedMessage))
} catch (e: IOException) {
LoadResult.Error(Exception(e.localizedMessage))
}
}
Configurar la paginación en la capa de presentación
Primero, pasemos a AssetsListViewModelEn la función getAssets(), comenzamos Obtener fuente de activos y convertirlo a flujo. En la función init, pase un flujo de objetos PagingData al estado.
private val _state = mutableStateOf(AssetsState())
val state: State = _stateinit {
_state.value = AssetsState(assets = getAssets().map { pagingData ->
pagingData.map {
it.toAssetPresentation()
}
})
}
private fun getAssets(): Flow> {
return Pager(PagingConfig(20)) { getAssetsSource }.flow
}
Entonces, en Pantalla de lista de activos Podemos recopilar el estado como PagingItems del modelo de vista y usarlo en nuestra lista.
@Composable
fun AssetsListScreen(
viewModel: AssetsListViewModel = hiltViewModel()
) {val lazyPagingItems = viewModel.state.value.assets?.collectAsLazyPagingItems()
...
}
Interfaz de usuario usando Jetpack Compose
empezaremos elemento de la lista de activos. Aquí podemos encontrar símbolos en verde formas, nombres y precios.
@Composable
fun AssetListItem(
asset: AssetPresentation
) {
Box(
modifier = Modifier
.fillMaxWidth()
.padding(20.dp)
) {
Row(horizontalArrangement = Arrangement.Start) {
Text(
text = asset.symbol,
fontStyle = FontStyle.Italic,
textAlign = TextAlign.Center,
color = Color.Black,
style = MaterialTheme.typography.body2,
modifier = Modifier
.align(Alignment.CenterVertically)
.graphicsLayer {
shadowElevation = 8.dp.toPx()
shape = RoundedCornerShape(8.dp)
clip = true
}
.requiredWidth(56.dp)
.background(color = ColorPrimary)
.padding(4.dp)
)
Spacer(modifier = Modifier.width(16.dp))
Text(
text = asset.name,
style = MaterialTheme.typography.body1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier
.align(Alignment.CenterVertically)
)
}Spacer(modifier = Modifier.width(32.dp))
Text(
text = "${String.format("%.2f", asset.priceUsd)} $",
style = MaterialTheme.typography.body1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier
.align(Alignment.CenterEnd)
)
}
}
existe Pantalla de lista de activos Solo usamos artículos de exhibición. columna perezosa
Box(modifier = Modifier.fillMaxSize()) {
LazyColumn(modifier = Modifier.fillMaxSize()) {
items(lazyPagingItems?.itemCount ?: 0) { index ->
lazyPagingItems?.get(index)?.let {
AssetListItem(
asset = it
)
}
}
}...
}
Espero que esta historia te sea útil.
Gracias por leer y que tengas un buen día 🙂