I'm trying to use Dagger 2 in an Android Project that has several Android Library modules and I'd like to be able to provide singleton scoped instances of classes from these modules.
Currently I'm able to define Components inside the library modules and inject the instances in the main Application module.
What I'm not able to do is to provide an instance as singleton.
The project structure is the following:
Project
├── app
├── library1
·
·
·
└── libraryN
In the libraries I'm defining the components this way:
@Component
public interface LibraryComponent {
// Provide instances of MyManager to MainComponent:
MyManager getMyManager();
}
And MyManager looks like this:
public class MyManager {
private static final String TAG = "MyManager";
@Inject
public MyManager() {
Log.d(TAG, "Creating MyManager");
}
}
In the main App I'm defining my component this way:
@ApplicationScope
@Component(dependencies = {LibraryComponent.class, Library2Component.class})
public interface MainComponent {
void inject(MainActivity target);
}
This is the Application class:
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;
}
}
If I add a scope to only one library component, then I'm able to provide the manager as a singleton. But if I try to do the same with one more library I'm getting the 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
Again, what I'd like to achieve is just to inject in my main Application project singleton scoped instances of some Managers provided by the Library projects.
As suggested by @EpicPandaForce, using Dagger Modules instead of Components solved my issue.
Following, the necessary changes that I had to make.
The first one is deleting the library Components and creating library Modules:
@Module
public class LibraryModule {
@Singleton
@Provides
MyManager provideMyManager(MyUtility myUtility) {
return new MyManager(myUtility);
}
}
Than just specify those Modules in the App Component, in place of the Component's dependencies:
@Singleton
@Component(modules = {LibraryModule.class, Library2Module.class})
public interface MainComponent {
void inject(MainActivity target);
}
And that's it, whit this code the Manager classes, annotated with the @Singleton scope, are correctly instantiated only once.
Try to unify the library components under a single component (eg.: AllLibrariesComponent), and then let your MainComponent have as dependency only the AllLibrariesComponent.
Library1:
@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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With