tutorial support para inyección for español dummies dependency dependencias dagger2 con android dependency-injection dagger

android - support - Usando Dagger para inyección de dependencia en constructores.



inject dependency dagger (4)

La publicación de Jake es genial, pero hay una manera más simple. Google creó la biblioteca de github.com/google/auto/tree/master/factory para crear la fábrica automáticamente en tiempo de compilación.

Primero, cree la clase A con la anotación @Provided y la anotación @Provided para inyectar argumentos:

@AutoFactory public class A { private DebugLogger logger; public A(@Provided DebugLogger logger, int amount, int frequency) { this.logger = logger; } }

Entonces la biblioteca crea AFactory clase de AFactory en tiempo de compilación. Así que solo necesitas inyectar la fábrica a un constructor de clase B

public class B { private final AFactory aFactory; @Inject public B(AFactory aFactory) { this.aFactory = aFactory; } public A createA(int amount, int frequency) { return aFactory.create(amount, frequency); } }

Por lo tanto, actualmente estoy rediseñando una aplicación de Android mía para usar Dagger . Mi aplicación es grande y complicada, y recientemente me encontré con el siguiente escenario:

El objeto A requiere una instancia especial de DebugLogger, que es un candidato perfecto para la inyección. En lugar de pasar el registrador, puedo inyectarlo a través del constructor de A. Esto se ve algo como esto:

class A { private DebugLogger logger; @Inject public A(DebugLogger logger) { this.logger = logger; } // Additional methods of A follow, etc. }

Hasta ahora esto tiene sentido. Sin embargo, A debe ser construido por otra clase B. Se deben construir múltiples instancias de A, por lo que, siguiendo la forma en que Dagger hace las cosas, simplemente inyecto un Provider<A> en B:

class B { private Provider<A> aFactory; @Inject public B(Provider<A> aFactory) { this.aFactory = aFactory; } }

Ok, bien hasta ahora. Pero espere, de repente, A necesita entradas adicionales, como un número entero llamado "cantidad" que es vital para su construcción. Ahora, mi constructor para A debe verse así:

@Inject public A(DebugLogger logger, int amount) { ... }

De repente este nuevo parámetro interfiere con la inyección. Además, incluso si esto funcionara, no habría manera de que yo pase la "cantidad" cuando recupero una nueva instancia del proveedor, a menos que me equivoque. Hay varias cosas que podría hacer aquí, y mi pregunta es ¿cuál es la mejor?

Podría refactorizar A agregando un método setAmount() que se espera que se llame después del constructor. Sin embargo, esto es feo porque me obliga a demorar la construcción de A hasta que se complete la "cantidad". Si tuviera dos de esos parámetros, "cantidad" y "frecuencia", tendría dos definidores, lo que significaría que Comprobación complicada para asegurar que la construcción de A se reanude después de que se llame a ambos setters, o tendría que agregar un tercer método a la mezcla, como por ejemplo:

(Somewhere in B): A inst = aFactory.get(); inst.setAmount(5); inst.setFrequency(7); inst.doConstructionThatRequiresAmountAndFrequency();

La otra alternativa es que no uso la inyección basada en el constructor y voy con la inyección basada en el campo. Pero ahora, tengo que hacer públicos mis campos. Esto no me sienta bien, porque ahora estoy obligado a revelar datos internos de mis clases a otras clases.

Hasta ahora, la única solución algo elegante que se me ocurre es usar la inyección de campo para los proveedores, como por ejemplo:

class A { @Inject public Provider<DebugLogger> loggerProvider; private DebugLogger logger; public A(int amount, int frequency) { logger = loggerProvider.get(); // Do fancy things with amount and frequency here ... } }

Aún así, no estoy seguro del momento, ya que no estoy seguro de si Dagger inyectará al proveedor antes de que se llame a mi constructor.

¿Hay alguna manera mejor? ¿Me estoy perdiendo algo sobre cómo funciona Dagger?


Lo que dice la publicación de Jake es perfectamente cierto. Dicho esto, nosotros (algunas de las personas de Google que trabajan con Guice y Dagger) estamos trabajando en una versión alternativa de "inyección asistida" o generación de fábrica automática que debe ser utilizada por Guice o Dagger o independiente, es decir, generará código fuente de clase de fábrica para usted. Estas clases de fábrica serán (si corresponde) inyectables como lo haría cualquier clase JSR-330 estándar. Pero aún no se ha publicado.

A la espera de una solución como esta, se recomienda el enfoque de Jake Wharton.


Lo que está hablando se conoce como inyección asistida y actualmente Dagger no lo admite de forma automática.

Puedes solucionar esto con el patrón de fábrica:

class AFactory { @Inject DebugLogger debuggLogger; public A create(int amount, int frequency) { return new A(debuggLogger, amount); } }

Ahora puede inyectar esta fábrica y usarla para crear instancias de A :

class B { @Inject AFactory aFactory; //... }

y cuando necesita crear una A con su ''cantidad'' y ''frecuencia'', utiliza la fábrica.

A a = aFactory.create(amount, frequency);

Esto permite que A tenga instancias final de los campos de registrador, cantidad y frecuencia mientras sigue usando la inyección para proporcionar la instancia del registrador.

Guice tiene un complemento de inyección asistida que esencialmente automatiza la creación de estas fábricas para usted. Ha habido una discusión en la lista de correo de Dagger sobre la forma apropiada para que se agreguen, pero no se ha decidido nada hasta el momento de este escrito.


Tiene un problema porque está mezclando inyectables y no inyectables en su constructor. Las reglas generales de inyección que le ahorrarán toneladas de angustia y mantendrán su código limpio son:

  1. Los inyectables pueden solicitar otros inyectables en su constructor, pero no para los nuevos.

  2. Newables puede solicitar otros newables en su constructor pero no inyectables.

Los inyectables son objetos de tipo de servicio, es decir, objetos que funcionan como un CreditCardProcessor, MusicPlayer, etc.

Los objetos nuevos son objetos de valor como CreditCard, Song, etc.