Dagger 2, módulos de biblioteca y @Singleton

Estoy tratando de usar Dagger 2 en un proyecto de Android que tiene varios módulos de la biblioteca de Android y me gustaría ser capaz de proporcionar instancias singleton escoped de clases de estos módulos.

Actualmente soy capaz de definir los componentes dentro de los módulos de la biblioteca e inyectar las instancias en el módulo de la aplicación principal.

Lo que no soy capaz de hacer es proporcionar una instancia como singleton.

La estructura del proyecto es la siguiente:

Project ├── app ├── library1 · · · └── libraryN 

En las bibliotecas estoy definiendo los componentes de esta manera:

 @Component public interface LibraryComponent { // Provide instances of MyManager to MainComponent: MyManager getMyManager(); } 

Y MyManager se ve así:

 public class MyManager { private static final String TAG = "MyManager"; @Inject public MyManager() { Log.d(TAG, "Creating MyManager"); } } 

En la aplicación principal estoy definiendo mi componente de esta manera:

 @ApplicationScope @Component(dependencies = {LibraryComponent.class, Library2Component.class}) public interface MainComponent { void inject(MainActivity target); } 

Esta es la clase de aplicación:

 public class App extends Application { private MainComponent component; @Override public void onCreate() { super.onCreate(); component = DaggerMainComponent.builder() .libraryComponent(DaggerLibraryComponent.create()) .library2Component(DaggerLibrary2Component.create()) .build(); } public MainComponent getComponent() { return component; } } 

Si agrego un ámbito a sólo un componente de biblioteca, entonces puedo proporcionar al administrador como singleton. Pero si trato de hacer lo mismo con una biblioteca más, estoy recibiendo el error:

 @com.codeblast.dagger2lib.ApplicationScope com.codeblast.dagger2lib.MainComponent depends on more than one scoped component: @Component(dependencies = {LibraryComponent.class, Library2Component.class}) ^ @com.codeblast.library.LibraryScope com.codeblast.library.LibraryComponent @com.codeblast.library2.Library2Scope com.codeblast.library2.Library2Component 

Una vez más, lo que me gustaría lograr es simplemente inyectar en mi proyecto de aplicación principal Singleton escoped instancias de algunos administradores proporcionados por los proyectos de la Biblioteca .

Como sugirió @EpicPandaForce, el uso de Dagger Modules en lugar de Components resolvió mi problema .

A continuación, los cambios necesarios que tuve que hacer.

El primero es borrar la biblioteca Componentes y crear módulos de biblioteca:

 @Module public class LibraryModule { @Singleton @Provides MyManager provideMyManager(MyUtility myUtility) { return new MyManager(myUtility); } } 

Más que especificar esos Módulos en el Componente de la Aplicación, en lugar de las dependencias del Componente:

 @Singleton @Component(modules = {LibraryModule.class, Library2Module.class}) public interface MainComponent { void inject(MainActivity target); } 

Y eso es todo, con este código, las clases Manager, anotadas con el alcance de @Singleton, se instancian correctamente una sola vez.

Intente unificar los componentes de la biblioteca bajo un solo componente (por ejemplo: AllLibrariesComponent) y, a continuación, deje que su MainComponent tenga como dependencia sólo AllLibrariesComponent.

Biblioteca1:

 @Component @Singleton public interface LibraryComponent { // Provide instances of MyManager to MainComponent: MyManager getMyManager(); } @Singleton public class MyManager { private static final String TAG = "MyManager"; @Inject public MyManager() { Log.d(TAG, "*** Creating MyManager 1 ***"); } } 

Library2:

 @Singleton @Component public interface Library2Component { // Provide instances of MyManager to MainComponent: MyManager2 getManager2(); } @Singleton public class MyManager2 { private static final String TAG = "MyManager"; @Inject public MyManager2() { Log.d(TAG, "*** Creating MyManager 2 *** "); } } 

App:

 @Singleton @Component public interface AllLibrariesComponent extends Library2Component, LibraryComponent{ } @PerApplication @Component(dependencies = AllLibrariesComponent.class) public interface MainComponent { void inject(MainActivity activity); } // .... // and the instantication in your application class: mainComponent = DaggerMainComponent.builder() .allLibrariesComponent(DaggerAllLibrariesComponent.create()) .build(); 
  • Dagger 2 inyecta error en AppCompatActivity
  • ¿Se puede hacer una inyección de daga en un método estático?
  • Dagger2 y Android
  • Mejor Dagger dependencia inyección basada en tipo de construcción y sabor?
  • Dagger 2.10 Subcomponentes y constructores de Android
  • Dagger 2: Inyectar el parámetro introducido por el usuario en el objeto
  • Dagger ejemplo construido a través de eclipse falla con 'Asegúrese de que la generación de código se ejecutó para este módulo.'
  • Dagger 2.2 método del módulo de constructor de componentes obsoleto
  • ¿Cómo inyectar dependencias pojo usando dagger 2?
  • Dagger - android.app.IntentService con @Inject
  • Dagger2 componente genérico método de inyección
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.