Android如何在Dagger 2.1.0中向SubComponent构建器添加外部依赖项(上下文)

时间:2017-10-28 20:21:44

标签: dagger-2 dagger

我根据谷歌sample

使用依赖注入

我可以传递的唯一外部依赖是通过AppComponent构建器

@Singleton
@Component(modules = {
        AndroidInjectionModule.class,
        AppModule.class,
        MainTabActivityModule.class,
        CoreActivityModule.class
})
public interface AppComponent {
    @Component.Builder
    interface Builder {
        @BindsInstance
        Builder application(Application application);
        AppComponent build();
    }
    void inject(MyApplication myApplication);
}

并像这样在应用程序中注入

@Override
    public void onCreate() {
        super.onCreate();

DaggerAppComponent
                .builder()
                .application(myApplication)
                .build().inject(myApplication);
...
}

根据Activity中注入的文件看起来像这样。我添加了我想要实现的目标。

public class YourActivity extends Activity {
  public void onCreate(Bundle savedInstanceState) {
    AndroidInjection
//.builder()                 THIS IS WHAT I WANT TO ACHIEVE
//.addActivityContext(this)  THIS IS WHAT I WANT TO ACHIEVE
//.build()                   THIS IS WHAT I WANT TO ACHIEVE
.inject(this);
    super.onCreate(savedInstanceState);
  }
}

但问题是如何向subComponent添加其他参数。

@Subcomponent
public interface CoreActivitySubComponent extends AndroidInjector<CoreAppActivity> {
//    @Subcomponent.Builder
//    interface Builder {
//        Builder addContext(Context context) //did not work
//        CoreActivitySubComponent build();   //did not work
//    }

//==or using abstract class
//   in this option I do not know where to add parameter to this builder
    @Subcomponent.Builder
    public abstract class Builder extends AndroidInjector.Builder<CoreAppActivity> {


    }

}

2 个答案:

答案 0 :(得分:0)

问题在于Dagger 2.1.0方法 AndroidInjection.inject(this); 应该在Activity和Fragment中使用,不提供任何构建器来添加外部依赖。

我想创建一个依赖于Activity / Fragment上下文的通用模块。

样品:

public class ToastController {

    private Context context;

    @Inject
    public ToastController(Context context) {
        this.context = context;
    }

    public void showToast(@StringRes int res) {
        Toast.makeText(context, context.getText(res), Toast.LENGTH_SHORT).show();;
    }
}

但我无法将其概括到某个级别,我只能提供一个上下文模块,而是我必须为使用此模块的每个Activity / Fragment创建绑定模块。

@Singleton
@Component(modules = {
        AndroidInjectionModule.class,
        AppModule.class,
        MainTabActivityModule.class,// IMPORTANT CLASS
})
public interface AppComponent {
    @Component.Builder
    interface Builder {
        @BindsInstance
        Builder application(Application application);
        AppComponent build();
    }
    void inject(MyApplication myApplication);
}

这是一个地方,我为每个活动提供上下文模块

@Module
public abstract class MainTabActivityModule 
    @ContributesAndroidInjector(modules = ContextMainTabActivityModule.class)//THIS MODULE
    abstract MainTabActivity contributeMainActivity();

}
使用@Binds注释

提供

和Context

@Module
public abstract class ContextMainTabActivityModule {
    @Binds
    abstract Context provideContext(MainTabActivity featureActivity);
}

=====================

可以通过根据sample

重写方法seedInstance来完成

我试过这个,但它对我不起作用

@Subcomponent.Builder
    public abstract class Builder extends AndroidInjector.Builder<CoreAppActivity> {

        abstract Builder addContextModule(ContextModule contextModule);

        @Override
        public void seedInstance(CoreAppActivity instance) {
            addContextModule(new ContextModule(instance));
        }
    }

下一堂课

@Module
public class ContextModule {

    private CoreAppActivity coreAppActivity;

    @Provides
    Context getContext() {
        return coreAppActivity.getBaseContext();
    }

    public ContextModule(CoreAppActivity coreAppActivity) {
        this.coreAppActivity = coreAppActivity;
    }

}

答案 1 :(得分:0)

您是否将ContextModule添加到与this answer类似的@Subcomponent? 我认为你的@Subcomponent应该是这样的:

@Subcomponent(module = {ContextModule.class})
interface MainTabActivityComponent extends AndroidInjector<CoreAppActivity> {
    @Subcomponent.Builder
    public abstract class Builder extends AndroidInjector.Builder<CoreAppActivity> {

        abstract Builder addContextModule(ContextModule contextModule);

        @Override
        public void seedInstance(CoreAppActivity instance) {
            addContextModule(new ContextModule(instance));
        }
    } 
}

最后不要忘记在绑定模块中包含此@Subcomponent

最后一个问题:这真的需要吗? 我发现使用Application以及ActivitiesFragments上的AndroidInjector会在我注入时给出正确的对应Context