studio medium google compiler annotationprocessor java android dependency-injection scope dagger-2

java - medium - dagger android processor



Daga 2 alcance y subcomponentes (1)

Un poco radical, pero para simplificar las cosas: todas las anotaciones de alcance no son más que azúcar sintáctica, incluido @Singleton .

Los alcances en su mayoría solo proporcionan controles de tiempo de compilación. Dependencias cíclicas, o errores sobre cosas que podrías haber pasado por alto. @Singleton es como cualquier otro ámbito, la única diferencia es que es una anotación ya existente y no tiene que crearla usted mismo. Puedes usar @MySingleton en @MySingleton lugar.

[...] daga está creando un objeto en algún grupo estático que existirá durante todo el ciclo de vida de la aplicación

No. Daga no hace nada estático. Tienes objetos componentes. Esos componentes contienen tus objetos creados por módulos. Si un objeto en un componente tiene el alcance del componente, solo se creará una vez en ese componente exacto . Si decide crear 2 objetos AppComponent , tendrá 2 objetos de cada objeto anotado @Singleton , cada uno dentro de su componente. Por eso debes mantener la referencia al componente. La mayoría de las implementaciones que he visto o usado mantienen su AppComponent dentro de su Application . Si haces esto, puedes usarlo como un singleton, todavía es solo un POJO.

[...] coloca el componente @PerFragment en la clase de Aplicación que vivirá mientras dure la Aplicación.

Sí. Como ya se ha cubierto en el párrafo anterior, es solo un objeto. Guarda la referencia, tú guardas los objetos. Deséchelo o cree uno nuevo y tiene nuevos objetos (definidos en este componente / ámbito). No obstante, debe mantener los componentes de la actividad o del ámbito de los fragmentos en cualquier lugar, además de en los de las actividades o los fragmentos, ya que mantenerlos, por ejemplo, en el componente de su aplicación, probablemente generará una pérdida de memoria. (Si no es así, probablemente no habría necesitado la actividad o el alcance del fragmento).

si dagger encuentra la anotación @Singleton , agregará una referencia estática al componente cuando se cree por primera vez y, en caso de cualquier otra anotación, no mantendrá la referencia al componente.

De nuevo, no. Nada estático. Objetos de Java antiguos simples. Puede tener múltiples componentes @Singleton con sus propios objetos, pero probablemente no debería (aunque esto es lo que hace posible / fácil la prueba de instrumentación, simplemente intercambiar componentes).

Tu error mencionado

SpiceManager no se puede proporcionar sin un constructor @Inject o desde un método anotado @ Provides- o @ Produces.

Esto significa que el componente con el que está intentando inyectar su objeto no puede encontrar ninguna forma de producir o proporcionar un SpiceManager . Asegúrese de proporcionarlo desde su AppComponent o en algún otro lugar, no le faltan anotaciones, etc.

Estoy tratando de hacer que mi aplicación sea mejor y el código sea más Dagger2 mantener usando Dagger2 Tomé una idea general, pero aún no puedo entender cómo se gestionan los ámbitos con Dagger2 . Dagger2 daga en mi proyecto (suena gracioso). ApplicationComonent componente ApplicationComonent y funciona perfectamente en mi proyecto. Aquí está mi código.

@Singleton @Component(modules = { ApplicationModule.class, ThreadingModule.class, NetworkModule.class, DatabaseModule.class, ServiceModule.class, ParseModule.class, PreferencesSessionModule.class}) public interface ApplicationComponent { ActivityComponent activityComponent(ActivityModule activityModule); void inject(BaseActivity baseActivity); void inject(MainAppActivity mainAppActivity); void inject(MyApplication application); void inject(BaseFragment baseFragment); void inject(MyService service); void inject(RegistrationIntentService service); }

Creo mi instancia de componente en la clase MyApplication como esta

private void initializeAndInjectComponent() { mApplicationComponent = DaggerApplicationComponent .builder() .threadingModule(new ThreadingModule(1)) .applicationModule(new ApplicationModule(this)) .networkModule(new NetworkModule( MyService.API_SERVER_BASE_URL, MyService.TIMEOUT)) .build(); mApplicationComponent.inject(this); }

Y puedo obtener el componente para inyectar en mis Activities

MyApplication application = MyApplication.get(this); application.getApplicationComponent().inject(this);

Todo funciona perfectamente.

Para agregar cada método y la clase de módulo se anota con el alcance @Singleton , todos los módulos relacionados con ApplicationComponent

Ahora quiero mejorar las dependencias y he visto muchos ejemplos con ámbitos personalizados como @PerActivity , @PerFragment . Tengo muchas preguntas, pero sobre esto más tarde.

Así que creé ActivityComponent

@PerActivity @Subcomponent( modules = { NetworkServiceModule.class, ActivityModule.class, PermissionModule.class }) public interface ActivityComponent { Activity activity(); void inject(BaseActivity baseActivity); }

Todos los módulos se ven así

@PerActivity @Module public class ActivityModule { private Activity mActivity; public ActivityModule(Activity activity) { this.mActivity = activity; } @Provides @PerActivity Activity provideActivity() { return this.mActivity; } }

Tengo dependencias siguientes en mi BaseActivity

// Dependencies from ApplicationComponent @Inject protected ApplicationSettingsManager mApplicationSettingsManager; @Inject protected ScheduledThreadPoolExecutor mPoolExecutor; // Dependencies from ActivityComponent @Inject protected SpiceManager mSpiceManager; @Inject protected PermissionController mPermissionController;

Y en mi método onCreate() estoy inyectando como sigue

MyApplication application = MyApplication.get(this); application.getApplicationComponent().activityComponent(new ActivityModule(this)).inject(this);

Antes de crear el subcomponente ActivityComponent era

MyApplication application = MyApplication.get(this); application.getApplicationComponent().inject(this);

Ahora tengo un error

Error:(34, 10) error: com.octo.android.robospice.SpiceManager cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method. BaseActivity.mSpiceManager [injected field of type: com.octo.android.robospice.SpiceManager mSpiceManager]

No puedo averiguar dónde está el problema, lo que me perdí. Mis preguntas sobre los alcances en daga2.

Todo menos @Singleton es ignorado por Dagger 2, ¿verdad? ¿No entiendo cómo se maneja la vida del componente? Solo tengo una idea

  1. Cuando se usa @Singleton anotación daga crea un objeto en algún grupo estático que existirá durante todo el ciclo de vida de la aplicación y se destruirá cuando se destruya la instancia del proceso JVM (dalvik VM, ART).

  2. Cuando usas cualquier otra anotación es solo para ti como desarrollador para mantener mejor el código, @PerActivity , @PerFragment es solo una anotación personalizada, nada más. Y en caso de que coloque el componente @PerFragment en la clase de Aplicación, vivirá mientras la Aplicación esté @PerFragment . Estoy en lo cierto

  3. Entonces entiendo esto de esta manera, si dagger encuentra la anotación @Singleton , agregará una referencia estática al componente cuando se cree por primera vez y, en caso de cualquier otra anotación, no mantendrá la referencia al componente.

Le agradecería cualquier ayuda con los problemas descritos anteriormente.

ACTUALIZAR

Gracias, David Medenjak por una gran respuesta. Comprendí mucho mejor a Dagger2 .

También acabo de encontrar el problema, en la medida en que estoy usando un componente de Activity separado ahora, olvidé dos líneas en ApplicationComponent y cambio la función en mi MainActivity a ActivityComponent lugar de ApplicationComponent , así que seguro que no pudo resolver las dependencias del subcomponente.

void inject(BaseActivity baseActivity); void inject(MainAppActivity mainAppActivity);

Ahora todo funciona perfectamente, me gusta Dagger2 y la arquitectura separada.