Ahora en Android con Koin — Parte 4 | de Arnaud Giuliani | abril 2023

Tomado del banner original: https://github.com/android/nowinandroidNow In Android es una aplicación de Android de código abierto que cubre las mejores prácticas para el desarrollo moderno de Android. El proyecto es mantenido por el equipo de Android de Google. Sugiero continuar nuestro recorrido con eso. ejecución construido con el marco de inyección de dependencia de Koin. Este es un buen momento para actualizar las prácticas, desde la estructura de componentes estándar hasta casos más avanzados. para este articulo Ahora propongo usar Koin Annotations en lugar de Koin DSL para configurar la inyección de todos los componentes de la aplicación. Es interesante ver cuánto puede mejorar la experiencia de escritura. Prepárate, tenemos mucho que ver juntos 👍 🚀

⚠️ La versión utilizada a continuación aún no es pública. @KoinWorker llegará pronto en la próxima versión

Anteriormente, en la Parte 3, vimos cómo configurar y usar las anotaciones de Koin con el marco de inyección de dependencia de Koin. Es realmente fácil ya que el procesador de anotaciones de Koin puede detectar muchos casos y generar su configuración de inyección de dependencia muy rápidamente. Ahora es el momento de sumergirse en más componentes del proyecto NowInAndroid. Tienes la referencia de todo el contenido para navegar por el código. Además, todo está disponible en línea en el repositorio de Github: https://github.com/InsertKoinIO/nowinandroid/Siguiendo el artículo de la Parte 2, ahora repasaremos los componentes comunes principales que usarán las funciones más adelante. Pero esta vez la configuración se hace con anotaciones. Como recordatorio, la aplicación Nia está desarrollada con Jetpack Compose y utiliza componentes de casos de uso y repositorios:

  • Repositorio para acceder a los datos (red, base de datos…)
  • Caso de uso para el manejo de la lógica de negocios

El módulo que encapsula todos estos componentes comunes es theDataKoinModule.kt:@Module(includes = [DaosKoinModule::class, DataStoreKoinModule::class, NetworkKoinModule::class, DispatchersKoinModule::class, DataUtilModule::class])@ComponentScan(«com.google.samples.apps.nowinandroid.core.data.repository») class DataKoinModuleEste módulo hace varias cosas:

  • escanea todas las clases de repositorio definidas en @ComponentScan
  • contiene módulos que declaran componentes de capas de datos subordinadas

Cada clase de repositorio simplemente se anota con una anotación @Single como esta: @Singleclass OfflineFirstAuthorsRepository(private val authorDao: AuthorDao,private val network: NiaNetworkDataSource,) Puede encontrar todas las clases de repositorio en el paquete de datos del código fuente. Para la capa de almacenamiento de la base de datos, debemos declarar nuestra instancia de la base de datos Room a través de una función usando el creador de Room API como esta: @Moduleclass DatabaseKoinModule {@Singlefun database(context: Context) =Room.databaseBuilder(context, NiaDatabase::class.java , «nia-database» ).build()}El parámetro de contexto aquí es la instancia de contexto de Android de Koin. En un segundo módulo, podemos reutilizar nuestra instancia de NiaDatabase a continuación en DAOs:@Module(incluye = [DatabaseKoinModule::class])class DaosKoinModule {@Singlefun authorDao(niaDatabase: NiaDatabase) = niaDatabase.authorDao()@Singlefun topicDao(niaDatabase: NiaDatabase) = niaDatabase.topicDao()@Singlefun newsResourcesDao(niaDatabase: NiaDatabase) = niaDatabase.newsResourceDao()}¡Eso es todo! Nuestra capa de base de datos está lista para ser insertada. Esta capa define las fuentes de datos, que son componentes que abstraen las llamadas a diferentes fuentes de datos. Por ejemplo: servicio web remoto, almacenamiento local de datos, etc. Por lo tanto, la interfaz de usuario no necesita saber de dónde provienen los datos. ¿Simplemente llama a la interfaz definida aquí? = nulo): ListaSuspender diversión getNewsResources(ids: List? = nulo): ListaSuspender diversión getTopicChangeList (después de: Int? = nulo): ListaSuspender diversión getAuthorChangeList (después de: Int? = nulo): ListaSuspender diversión getNewsResourceChangeList (después de: Int? = nulo): Lista}Primero necesitamos declarar un despachador de rutina estándar directamente en un módulo:@Moduleclass DispatchersKoinModule{@Singlefun-Dispatcher( ) = Dispatcher.IO}

En un entorno de prueba, simplemente necesita redefinir un tipo de CoroutineDispatcher para especificar el tipo que necesita. Simplemente agregue la nueva definición y sobrescribirá la existente.

El módulo de red declara NiaNetworkDatasource y está organizado en 2 sabores:

  • Demostración — con datos locales
  • prod – para datos en línea

NetworkKoinModule contiene la implementación de tipo correcta: @Module(incluye = [FlavoredNetworkKoinModule::class])clase NetworkKoinModule {@Singlefun json() = Json {ignoreUnknownKeys = true}}Variante de demostración en el módulo de red La variante de demostración usa la API del almacén de datos y la API de Protobuff se usa para almacenar datos locales para mostrarlos como arquitectura sin conexión primero.@Module(incluye = [DispatchersKoinModule::class])@ComponentScan(«com.google.samples.apps.nowinandroid.core.network.fake»)class FlavoredNetworkKoinModule{@Singlefun assetManager(context:Context) = FakeAssetManager(context.assets::open)}A continuación se muestra la implementación de demo – Fuente de datos declarada como singleton: @Singleclass FakeNiaNetworkDataSource(private val ioDispatcher: CoroutineDispatcher,private val networkJson: Json,private val assets: FakeAssetManager = JvmUnitTestFakeAssetManager,) : NiaNetworkDataSourceLa versión en línea se declara con el siguiente módulo: @Module(incluye = [DispatchersKoinModule::class])@ComponentScan(«com.google.samples.apps.nowinandroid.core.network.retrofit»)class FlavoredNetworkKoinModuleEste módulo analiza la implementación de la actualización:@Singleclass RetrofitNiaNetwork(networkJson: Json): NiaNetworkDataSourceUna última parte trata sobre la API de persistencia del almacén de datos, que se utiliza para declarar almacenamiento de datos locales. Compruebe el módulo de persistencia del almacén de datos que declara los componentes necesarios para NiaPreferencesDatasource. Antes de ejecutar nuestras funciones, tenemos algunos componentes de casos de uso que usan DataKoinModule. Estos componentes de casos de uso son componentes de lógica empresarial reutilizables. Se extraen del dominioKoinModule:@Module(incluye = [DataKoinModule::class])@ComponentScanclass DomainKoinModule Puede notar que no especificamos qué paquete escanear. Esto significa que el módulo escanea el paquete actual y los subpaquetes en busca de componentes anotados:Cada componente de caso de uso se declara con la anotación @Factory. Esto hará que Koin cree una nueva instancia cada vez que la necesitemos.

¿Por qué no una instancia singleton? Porque estos componentes de casos de uso se usan con un ViewModel después del ciclo de vida de Android. Si los hacemos como singleton, correríamos el riesgo de tener referencias a un ViewModel que será destruido por la aplicación.

Finalmente, estamos listos para usar todo esto en nuestro módulo de funciones. Luego, cada uno incluye DomainKoinModule o DataKoinModule para beneficiarse de los componentes comunes: @Module(incluye = [DomainKoinModule::class,StringDecoderKoinModule::class])@ComponentScan(«com.google.samples.apps.nowinandroid.feature.author»)class AuthorKoinModule Al escanear el paquete correcto en nuestro módulo, podemos declarar nuestras instancias de ViewModel de esta manera: @KoinViewModelclass AuthorViewModel(savedStateHandle: SavedStateHandle, stringDecoder : StringDecoder , private val userDataRepository: UserDataRepository, authorsRepository: AuthorsRepository, getSaveableNewsResourcesStream: GetSaveableNewsResourcesStreamUseCase) : ViewModel() Finalmente, debemos declarar nuestros componentes de SyncWorker para preparar el contenido sin conexión de forma asíncrona. Esto consiste en un módulo:@Module@ComponentScanclass SyncWorkerKoinModuleLas siguientes definiciones son escaneadas por el módulo.@Singleclass WorkManagerSyncStatusMonitor(Context:Context) : SyncStatusMonitorY el componente SyncWorker declarado con la anotación @KoinWorker. Este será el equivalente de trabajador { } DSL:@KoinWorkerclass SyncWorker (private val appContext: Context,workerParams: WorkerParameters,private val niaPreferences: NiaPreferencesDataSource,private val topicRepository: TopicsRepository,private val newsRepository: NewsRepository,private val authorsRepository: AuthorsRepository,private val ioDispatcher: CoroutineDispatcher,) : CoroutineWorker(appContext, workerParams), SynchronizerSyncWorker se declara con Workmanager Koin Factory. Esto debe activarse al inicio de la siguiente manera:Koin comienza en la clase NiaApplication

Deja una respuesta

Tu dirección de correo electrónico no será publicada.