Dagger 2 en el proyecto Android Dynamic Multimodule Lukáš Sztefek | Octubre de 2020

Los proyectos de varios módulos se están adoptando rápidamente en la última generación de aplicaciones de Android. Los módulos de Gradle pueden depender entre sí de varias maneras. Este artículo se centra en un enfoque basado en módulos de función dinámica, donde el módulo de función depende del módulo de aplicación principal y no al revés. La inyección de adicciones en el mundo de los multimódulos no es tan sencilla como cabría esperar, y tienes que lidiar con muchos obstáculos.

El código fuente relacionado con este artículo está disponible en el siguiente texto Almacenamiento de GitHub. Debido a la colisión de nombres entre el módulo Gradle y el módulo Dagger, se utilizará una variante grande, el módulo, cuando se utilice el módulo Dagger.

La jerarquía de módulos en el proyecto descrito se puede dividir en tres grupos. Primero, bibliotecas, es un lugar para las bibliotecas de Android y Kotlin, que están diseñadas para su uso en módulos de aplicaciones y funciones.

solicitud el grupo se encarga de Application instancias de la clase y la principal Activity. Finalmente función el grupo contiene módulos dinámicos con lógica relacionada con la interfaz de usuario: Fragmentos, ViewModels, etc.

Jerarquía de módulos de Gradle

los :network y :database los módulos contienen lógica relacionada con IO. Se combinan junto con :common (cadenas / dimensiones / etc.) a una fuente de datos en :core módulo. Módulo :service se encarga de un simple Android Service ejecutar en módulos de función.

Veamos la jerarquía desde el punto de vista de Dagger. Es Miercoles CoreComponent. Combina módulos de módulos de biblioteca y proporciona instancias de biblioteca en ApplicationComponent, ServiceComponent y componentes funcionales, por ejemplo HomeComponent.

Jerarquía de componentes de daga

CoreComponent tiene un alcance único, lo que significa que solo hay una instancia de este componente en toda la aplicación. Debido a que los componentes dependientes no pueden depender de un componente definido, también se definen los componentes Aplicación / Servicio / Característica. Pasemos a la implementación.

Será fácil. losDatabase la clase en sí es solo una clase ficticia, así que no se moleste en implementarla. De hecho, hay dos partes básicas. Inicialmente, el propio módulo Dagger.

A continuación, necesitamos crear un contrato de módulo, una interfaz que nos diga qué dependencias proporciona este módulo en particular. Lo necesitaremos más tarde.

Debido a que el módulo de red es casi idéntico al módulo de base de datos, lo omitiremos.

CoreComponent combina módulos de almacenamiento en un solo componente. Es una pieza bastante estándar, con una diferencia. CoreComponent implementa los contratos que mencioné anteriormente. ¿Por qué?

Cuando un componente depende de otro, solo los tipos definidos explícitamente en la interfaz del componente se proporcionan desde el componente. Ya que HomeComponent depende de CoreComponent, debemos proporcionar Database a través de un contrato; De lo contrario, no podremos administrar la inyección. Database por ejemplo HomeComponent. Los contratos también tienen un efecto secundario agradable. Puede ocultar algunos de los tipos proporcionados si no los define en la interfaz del contrato.

Tenemos nuestro componente definido. Ahora tenemos que crear una instancia y guardarla en algún lugar. Necesitamos acceso CoreComponent desde varios lugares (aplicación / módulo de funciones /…), por lo que lo almacenamos en Kotlin object.

En la primera solicitud, el componente se crea de forma perezosa y la instancia se almacena en un archivo SingletonHolder.

Empecemos con HomeComponent que combina los tipos proporcionados CoreComponent y HomeModule. Puede notar que no contiene un estándar inject() método. En cambio, existe plus() un método para crear un subcomponente asociado con un fragmento particular, HomeFragment en este caso. Puede pensar en una subcarpeta como una extensión de un componente principal, por lo que proporciona todo lo que hace un padre, pero puede agregar algo adicional. Todos los fragmentos se inyectan a través de sus propios subcomponentes y nunca a través de ellos. HomeComponent solo.

Una vez más, nos enfrentamos al problema de dónde almacenar HomeComponent. Los módulos de función se encargan de la interfaz de usuario y son básicamente un conjunto de fragmentos con lógica relacionada. Con esto en mente, podemos ocultar el componente en el fragmento base. La desventaja de esta solución es que tenemos que definir una clase básica de fragmentos para cada módulo de función individual, pero esto es inevitable porque los módulos de función no dependen unos de otros. Nuestros módulos de funciones también son dinámicos, lo que significa que puede optar por no incluir el módulo en el APK final en cualquier momento.

Ya casi hemos terminado. Empecemos por la inyección. Como se mencionó, HomeFragment tiene su propio subcomponente con inject() Método y Módulo propio. HomeFragmentModule proporciona atributos relacionados con los fragmentos, como datos de intención, que luego el modelo de visualización puede insertar.

La única pieza que falta es la nuestra HomeFragment. Como puede ver, podemos insertar dependencias de todos los módulos.

Dagger es una herramienta poderosa pero compleja. Podría traer un cierto estándar, pero también orden a las aplicaciones que creamos. Espero que este artículo le haya dado una visión general de que la integración de dependencias en un proyecto multimodular dinámico es posible y no tan difícil al final del día.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *