How to get MainActivity inside module using AndroidInjector
With the help, dagger-android
you can simply write the following and successfully inject the application dependencies:
@Module
public abstract class MainActivityModule {
@ContributesAndroidInjector
abstract MainActivity contributesMainActivity();
}
@Singleton
@Component(modules = {
AndroidSupportInjectionModule.class,
AndroidInjectionModule.class,
AppModule.class,
MainActivityModule.class
})
public interface ApplicationComponent {
void inject(BaseApplication baseApplication);
@Component.Builder
interface Builder {
@BindsInstance
Builder application(Application application);
ApplicationComponent build();
}
}
@Module
public abstract class AppModule {}
public class MainActivity extends AppCompatActivity implements
HasSupportFragmentInjector {
@Inject
DispatchingAndroidInjector<Fragment> dispatchingAndroidInjector;
@Inject
Whatever whatever;
@Override
protected void onCreate(Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public AndroidInjector<Fragment> supportFragmentInjector() {
return dispatchingAndroidInjector;
}
}
public class BaseApplication extends Application implements
HasActivityInjector {
@Inject
DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;
@Override
public AndroidInjector<Activity> activityInjector() {
return dispatchingAndroidInjector;
}
@Override
public void onCreate() {
DaggerApplicationComponent.builder()
.application(this)
.build()
.inject(this);
super.onCreate();
}
}
public class Whatever {
private final FragmentManager fragmentManager;
@Inject
Whatever(MainActivity mainActivity) {
this.fragmentManager = mainActivity.getSupportFragmentManager();
}
}
A very trivial example. Basically hook everything up to be able to get the object Whatever
with the correct fragment manager. This is fine and works.
However, what if I want to use the main activity inside the module? Let's say I want to Whatever
explicitly display the dependency with the fragment manager by changing the constructor argument:
@Inject
Whatever(FragmentManager fragmentManager) {...}
Now I have to provide this dependency. How can I do that? So I tried the following:
@Module
public abstract class MainActivityModule {
@ContributesAndroidInjector
abstract MainActivity contributesMainActivity();
@Provides
static FragmentManager providesFragmentManager(MainActivity activity) {
return activity.getSupportFragmentManager();
}
}
Now the dagger complains that he cannot find it @Providers
for MainActivity
. I thought the method @ContributesAndroidInjector
would be able to provide activity. I am also a bit puzzled about how it has no problem with dependency injection in the first case, but now it cannot do it.
I also tried to create a factory for this, for example:
public FragmentManagerFactory {
private final FragmentManager fm;
@Inject
FragmentManagerFactory(MainActivity mainActivity){
this.fm = mainActivity.getSupportFragmentManager();
}
public FragmentManager get() {
return fm;
}
}
@Module
public abstract class MainActivityModule {
@ContributesAndroidInjector
abstract MainActivity contributesMainActivity();
@Provides
static FragmentManager providesFragmentManager(FragmentManagerFactory fragmentManagerFactory) {
return fragmentManagerFactory.get();
}
}
The end ends with the same error.
Has anyone been able to do this? Before this was pretty straightforward, one could just build a module with an instance, MainActivity
save it in a field and provide that. Now ... everything happens behind the curtains.
Would be grateful for your help!
source to share
In my setup, I have a package di/
at the root sub-di-packages
in my package ui/
. In the package, ui/di
I have declared the following module and component:
@dagger.Module
public class MainActivityModule {
@Provides
FragmentManager provideFragmentManager(MainActivity mainActivity) {
return mainActivity.getSupportFragmentManager();
}
}
MainActivitySubcomponent
@Subcomponent(modules = MainActivityModule.class)
public interface MainActivitySubcomponent extends AndroidInjector<MainActivity> {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<MainActivity> {
}
}
in the di
top-level package where I save ApplicationComponent
mine, I have an additionalmodule
@Module(subcomponents = {MainActivitySubcomponent.class })
public abstract class BuildersModule {
@Binds
@IntoMap
@ActivityKey(MainActivity.class)
abstract AndroidInjector.Factory<? extends Activity> mainActivityBinder(MainActivitySubcomponent.Builder builder);
}
And as you can imagine BuildersModule
, is part @Component(modules = {
of ApplicationComponent
.
Disclaimer: <Sub> I'm new to dagger2 and I am still trying to find a lot of stuff. There may be better ways to achieve what you need. sub>
source to share