How to inject current activity in a collaborator using Dagger 2.11 Android injector

不打扰是莪最后的温柔 提交于 2019-12-04 14:53:52

问题


I used to inject the current activity or activity context on some collaborators shared by several activities injecting the parent activity (BaseActivity or AppCompactActivity). But for some reason I cannot do it using Dagger 2.11 Android Injector.

This is my Activity Module:

@Module
public class ActivityModule {

    private final Activity activity;
    public ActivityModule(Activity activity) {
        this.activity = activity;
    }

    @Provides
    @PerActivity
    ActColaborator provideActCollaborator() {
        return new ActColaborator();
    }

    @Provides
    @PerActivity
    Activity provideActivity() {
        return activity;
    }
}

I try to inject those classes:

    @Inject
    public Navigator(ActColaborator actColaborator, 
                     BaseActivity activity) {
        this.actColaborator = actColaborator;
        this.activity = activity;
    }

But I get a

BaseActivity cannot be provided without an @Inject constructor or from an @Provides-annotated method.

If I remove the BaseActivity stuff, ActColaborator is correctly injected. The problem is that ActivityModule is not longer instantiated in the Activity passing it the Activity itself as it used to be:

    //old, pre Android-injector code
    this.activityComponent = getApplicationComponent()
            .getActivityComponentBuilder()
            .activityModule(new ActivityModule(this))
            .build();

So I have no idea of how to make the current activity available for injection into its collaborators.

More info as requested: I have three different component classes for the three activities, but all of them like this:

@PerActivity
@Subcomponent
public interface MainActivityComponent extends     AndroidInjector<MainActivity> {
    @Subcomponent.Builder
    abstract class Builder extends AndroidInjector.Builder<MainActivity> {
    }
}

And the ActivityBindingModule:

@Module(subcomponents = {
        MainActivityComponent.class,
        DetailActivityComponent.class,
        AnotherActivityComponent.class
})
abstract public class ActivityBindingModule {
    @Binds
    @IntoMap
    @ActivityKey(MainActivity.class)
    abstract AndroidInjector.Factory<? extends Activity> mainActivityInjectorFactory(
            MainActivityComponent.Builder builder);
.....

回答1:


Ok, finally found what the problem was. Using components with dependency or subcomponents I'm able to create the ActivityComponent at the BaseActivity level and then use it to inject properties into the top level activities.

Thas way, when I injected Activity into collaborators the current ActivityComponent that held the current Activity was used. Easy.

The problem with Android Injector is that we don't instantiate the ActivityComponent from the code anymore, it is AndroidInjector who does the magic, so we need to provide each Activity in its own module.

For example Main:

@Module
public abstract class MainActivityModule {
    @Provides
    @PerActivity
    static Activity provideActivity(MainActivity activity) {
        return activity;
    }
}

Detail:

@Module
public abstract class DetailActivityModule {
    @Provides
    @PerActivity
    static Activity provideActivity(DetailActivity activity) {
        return activity;
    }
}

Common provides:

@Module
public abstract class ActivityModule {
    @Provides
    @PerActivity
    static ActColaborator provideActCollaborator() {
        return new ActColaborator();
    }
}

Then we declare them in Main:

@PerActivity
@Subcomponent(modules = { ActivityModule.class, MainActivityModule.class})
public interface MainActivityComponent extends AndroidInjector<MainActivity> {
    @Subcomponent.Builder
    abstract class Builder extends AndroidInjector.Builder<MainActivity> {
    }
}

And detail:

@PerActivity
@Subcomponent(modules = { ActivityModule.class, DetailActivityModule.class})
public interface DetailActivityComponent extends AndroidInjector<DetailActivity> {
    @Subcomponent.Builder
    abstract class Builder extends AndroidInjector.Builder<DetailActivity> {
    }
}

And finally, we can inject the current activity in our shared collaborator:

private final Activity activity;

@Inject
public Navigator(Activity activity) {
    this.activity = activity;
}


来源:https://stackoverflow.com/questions/44701292/how-to-inject-current-activity-in-a-collaborator-using-dagger-2-11-android-injec

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!