How does an Android application in one gradle module include dagger @Modules defined in an other Android Library (.aar)?
I'm trying to have a generic library that provides a set of functionality defined thru dagger @Module's able to have have them injected into Applications that depend on that library
@Singleton
@Component(modules = {
AndroidSupportInjectionModule.class,
LibraryAppModule.class
})
public interface LibraryComponent extends AndroidInjector<DaggerApplication> {
@Component.Builder
interface Builder {
@BindsInstance
Builder application(Application application);
LibraryComponent build();
}
void inject(LibraryApplication app);
@Override
void inject(DaggerApplication instance);
}
@Module
public class LibraryAppModule {
@Provides
@Singleton
Context provideContext(Application application) {
return application;
}
@Singleton
@Provides
ServiceFoo provideServiceFoo(Context context) {
return new ServiceFoo(context);
}
@Singleton
@Provides
ServiceBar provideServiceBar(Context context, ServiceFoo serviceFoo) {
return new ServiceBar(context, serviceFoo);
}
}
Now in the Application that has a dependency for this library (build.gradle) I've tried the following:
implementation project(":Library")
Application using the library
@Singleton
@Component(modules = {
AndroidSupportInjectionModule.class,
LibraryAppModule.class
})
public interface ExampleApplicationComponent extends AndroidInjector<DaggerApplication> {
@Component.Builder
interface Builder {
@BindsInstance
Builder application(Application application);
ExampleApplicationComponent build();
}
void inject(ExampleApplication app);
@Override
void inject(DaggerApplication instance);
}
This is an example of the place where I'm getting the issue (a null object). This is in a separate module that depends on the library.
public class MainActivity extends AppCompatActivity {
@Inject
ServiceFoo serviceFoo;
@Inject
ServiceBar serviceBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
serviceFoo.downloadImages();
serviceBar.uploadImages();
}
}
I expect to see the LibraryAppModule's services to be available in my Activities using @Inject. What am I doing wrong?
In order to resolve the issue 2 things needed to be done.
MainActivity
had to extend DaggerAppCompatActivity
(this ensures during onCreate()
for our Activity that inject()
is called, but for this to work there needs to be an AndroidInjector
for the Activity.@ContributesAndroidInjector
within a module that I defined and installed into the ExampleApplicationComponent
@Module
public abstract class ExampleApplicationActivityBuilder {
@ContributesAndroidInjector
abstract MainActivity bindMainActivity();
}
Now within the MainActivity
, the Services I want injected from the library module are non-null.
Here's is a git commit that shows the difference implementing this fix. https://github.com/PeregrineFalcon/DaggerExampleLibrary/commit/1ebfdecfa3684c7ac124b9f6a4cecd23712a74fd
Hope this helps someone else who trying to do a multi-module Dagger Android project with @Modules
provided through the library.