Ahora en Android con Koin — Parte 2 | de Arnaud Giuliani | diciembre 2022

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.Hagamos un recorrido por los componentes básicos comunes que nos brindan los componentes esenciales con los que escribir nuestras características.Las pantallas de la aplicación NowInAndroid se desarrollan con Jetpack Compose, utilizando componentes de repositorio y caso de uso:

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

Abramos DataKoinModule.kt para ver las definiciones de los componentes de nuestro repositorio:Componentes de datos comunes Todos los componentes del repositorio se declaran con la palabra clave singleOf más una cláusula bind() para indicar el tipo que está vinculado. Esto crea cada uno como una instancia única. Es una buena idea usar la función include() para enumerar explícitamente cada módulo Koin necesario para una definición del módulo actual. Esto también expresa un vínculo fuerte que puede ser utilizado por la API de verificar () para verificar nuestra configuración de Koin. Los componentes de la capa de datos se pueden declarar como instancias singleton. La capa de datos es independiente de la capa de UI: no es necesario asociarla con un ciclo de vida. Para los componentes del dominio de casos de uso, los veremos en detalle más adelante en la sección.Capas de arquitectura de https://developer.android.com/topic/architectureLos primeros módulos de datos que veremos son los componentes de la base de datos indaosKoinModule. El proyecto utiliza Room. Para declarar una instancia de base de datos Room, debemos crearla usando la función de construcción Room.databaseBuilder(). Esta instancia se registra como singleton y los componentes de DAO hacen referencia a ella. Debajo de la base de datosKoinModule declara la definición de la instancia de la base de datos:Declarar la base de datos de la habitación Simplemente usamos una sola definición seguida de una función para ejecutar. Observe aquí que usamos la función androidContext() para obtener el contexto de Android de Koin. A continuación, en daosKoinModule, es bastante fácil declarar cada DAO. Cada uno de ellos está referenciado por la interfaz de NiaDatabase. Podemos referirnos a cada DAO de la siguiente manera. Usamos la expresión obtener() para obtener nuestra instancia de base de datos y usarla para llamar a nuestra instancia DAO de esta manera:Declarar DAO Cada uno de estos DAO se define con la palabra clave single (instancia singleton). Añadimos el módulo de definición de base de datos. En Dagger Hilt, la filosofía sigue siendo la misma, pero sigue siendo detallada:Hilt NiaDatabase explicaciónExplicación de Hilt DAO Pasemos a los componentes de DataStore en la siguiente sección. En esta parte, debemos prepararnos para crear una instancia de DataStoreFactory para leer datos sin conexión. Abramos dataStoreKoinModule para ver estos componentes:Módulo DataStoreNecesitamos varios singletons aquí:

  • UserPreferencesSerializer pasó a nuestro DataStore para serializar datos de UserPreferences
  • DataStoreFactory la propia instancia de DataStore
  • NiaPreferencesDataSource Componente de origen de datos que utiliza DataStore para leer datos locales

En este módulo, debemos incluir las corrutinas del «distribuidor predeterminado» de Kotlin. Esto está incluido en nuestro módulo y se puede escribir de la siguiente manera:Declaración de corrutinas de despachador predeterminadas Tenga en cuenta que podemos anular fácilmente dicha definición en un entorno de prueba al proporcionar una nueva definición que anula la definición predeterminada. Si tiene varias definiciones del mismo tipo, también puede agregar un calificador. El módulo de red es un caso interesante: necesitamos cargar diferentes definiciones de implementación según el sabor del módulo. Tenemos 2 sabores: Demo (contenido de demostración estático) y Prod (contenido solicitado a través de la red).¿Cómo usar dinámicamente la implementación de sabor correcta?Escribamos primero el archivo networkKoinModule. Este módulo incluye la implementación secundaria:El módulo de red Podemos declarar todas las definiciones comunes utilizadas por los módulos incluidos (como la instancia del serializador JSON) aquí. Llamar a include(networkFlavoredKoinModule) carga el módulo Koin apropiado. A partir de ahí, escribamos el módulo networkFlavoredKoinModule para cada tipo. Por supuesto, el proyecto vinculará y compilará el archivo correcto. La carpeta de sabor de demostración:Demo FlavorEl archivo Demo Flavor NetworkFlavoredKoinModule que declara una implementación falsa:Módulo de red de demostraciónLa carpeta Prod Flavor:Prod FlavorEl archivo Prod FlavoredKoinModule de la red, que declara una implementación de actualización:Implementación Prod NiaNetworkDataSource Cada implementación proporciona un componente NiaNetworkDataSource. No necesitamos declarar o incluir una definición json ya que Koin la encontrará en el módulo principal. Ahora que tenemos componentes centrales que nos ayudan a trabajar con nuestros datos, podemos tener componentes dedicados a la lógica comercial y permitirnos reutilizarlos a nivel de la interfaz de usuario. Abramos el archivo domainKoinModule para ver nuestras definiciones de casos de uso:Definiciones de casos de uso Cada componente de caso de uso se define aquí como una «Fábrica». ¿Por qué? Queremos asegurarnos de tener una unidad de lógica empresarial «sin estado» y evitar tener en cuenta cualquier cosa relacionada con la interfaz de usuario. Estos componentes de casos de uso lanzan flujos de rutinas para escuchar las actualizaciones de datos entrantes. No queremos mantener la referencia de flujo entre pantallas.GetFollowableTopicsStream UsecaseUsing factoryOf asegura que cada vez que lo solicitemos recreemos una instancia y eliminemos las instancias usadas anteriormente (destruyamos la instancia). Finalmente, un componente especial e importante de este proyecto es la clase SyncWorker dedicada para resincronizar datos con repositorios. Esto ayuda a recopilar datos para la estrategia «Offline First»: analizamos los datos de forma local y remota. Podemos ver datos ya obtenidos mientras solicitamos datos nuevos de forma remota y evitamos mostrar contenido en blanco al usuario. Como puede ver, esta clase requiere casi todos nuestros componentes comunes:Clase SyncWorker: para admitir la sincronización del repositorio de datos, abramos el archivo syncWorkerKoinModule para declarar nuestro WorkManager. Puede ver que simplemente necesitamos declarar nuestro componente con la palabra clave workerOf, y eso es todo:Declare Sync Worker No olvide iniciar WorkManager Koin Factory al iniciar la aplicación con la función workManagerFactory():Configuración de WorkManager con KoinLa llamada Sync.initialize() le solicita que inicialice la sincronización de datos para el contenido sin conexión. No dude en leer la documentación para obtener más detalles: https://insert-koin.io/docs/reference/koin-android/workmanager Ahora estamos listos para poner todo en una función Jetpack Compose componible. En nuestra pantalla AuthorRoute componible, usamos la función koinViewModel() para obtener el ViewModel.Inyectar ViewModel en ComposePara declarar un componente de ViewModel, simplemente necesitamos la palabra clave viewModelOf seguida de nuestro constructor de clase:Declarar AuthorViewModelCon tal palabra clave, su ViewModel se puede inyectar automáticamente con el parámetro SavedStateHandle cuando sea necesario.Constructor de la clase AuthorViewModel

Deja una respuesta

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