ContributesAndroidInjector 模块必须设置

edw*_*ock 0 android dagger-2

我正在尝试将活动依赖项注入片段呈现器。\n应用程序结构非常简单。

\n\n

TabsActivity - viewpager

\n\n

-- TabFragment - 页面项

\n\n

-- [...]

\n\n

TabsActivity显示视图\n TabsActivityModule - 提供FragmentManager(例如)和TabsActivity的一些内容

\n\n

TabFragmentModuleTabFragment提供了一些东西。\n每个TabFragment都有自己的PresenterPresenter注入TabActivityModule 依赖项。

\n\n

就我而言 - Presenter 注入FragmentManager

\n\n

这是代码:

\n\n

应用类

\n\n
class App extends Application implements HasActivityInjector {\n    @Inject\n    DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;\n\n    @Override\n    public AndroidInjector<Activity> activityInjector() {\n        return dispatchingAndroidInjector;\n    }\n   /*\n   blah blah creating app component onCreate() ...\n       DaggerAppComponent\n            .builder()\n            .context(this)\n            .build()\n            .inject(this);\n   */ \n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

根应用程序组件

\n\n
@Singleton\n@Component(modules = {InjectorsModule.class})\npublic interface AppComponent {\n\n    @Component.Builder\n    interface Builder {\n        @BindsInstance\n        Builder context(Context context);\n\n        AppComponent build();\n    }\n\n    void inject(App app);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这里是 android 视图贡献者InjectorsModule

\n\n
@Module(includes = {AndroidSupportInjectionModule.class})\npublic abstract class InjectorsModule {\n\n    @ActivityScope\n    @ContributesAndroidInjector(modules = {TabsActivityModule.class})\n    abstract TabsActivity tabsActivityInjector();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

活动选项卡活动模块

\n\n
@Module\npublic abstract class TabsActivityModule {\n\n    @Provides\n    @ActivityScope\n    public FragmentManager provideFragmentManager(TabsActivity activity) {\n        return activity.getFragmentManager();\n    }\n\n    @Provides @Named("activity")\n    @ActivityScope\n    public Context provideActivityContext(TabsActivity activity) {\n        return activity;\n    }\n\n    // Here contributes tab fragment\n    @FragmentScope\n    @ContributesAndroidInjector(modules = {TabFragmentModule.class})\n    public abstract TabFragment tabFragment();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

片段选项卡FragmentModule

\n\n
@Module\npublic abstract class TabFragmentModule {\n    @Provides @Named("answer")\n    @FragmentScope\n    public int provideSomeInt() {\n        return 42;\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

最后,仅举个例子 - TabPresenter

\n\n
public class TabPresenter {\n    @Inject @Named("answer") int mAnswer;\n    @Inject @Named("activity") mActivityContext;\n    @Inject FragmentManager mFragmentManager;\n\n    @Inject\n    public TabPresenter() {}\n\n    public void doNothingWithAnswerAndContextAndFragmentManager() {\n        mAnswer *= 1;\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在这一切之后,构建以成功状态完成。但在运行时,我在片段注入时立即收到 InvalidStateException:

\n\n
onAttach(Activity activity) {\n    AndroidInjection.inject(this);\n    super.onAttach(activity);\n} \n
Run Code Online (Sandbox Code Playgroud)\n\n

异常堆栈跟踪:

\n\n
FATAL EXCEPTION: main\nProcess: com.example.drive.dagger2new, PID: 3064\n java.lang.RuntimeException: \nUnable to start activity \nComponentInfo{com.example.drive.dagger2new/com.example.ui.TabsActivity}:\njava.lang.IllegalStateException:\ncom.example.dagger.modules.main.TabsActivityModule must be set\n\n at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2680)\n at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2741)\n at android.app.ActivityThread.-wrap12(ActivityThread.java)\n at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1488)\n at android.os.Handler.dispatchMessage(Handler.java:102)\n at android.os.Looper.loop(Looper.java:154)\n at android.app.ActivityThread.main(ActivityThread.java:6169)\n at java.lang.reflect.Method.invoke(Native Method)\n at     com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:888)\n at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:778)\n\nCaused by: java.lang.IllegalStateException: com.example.dagger.modules.main.TabsActivityModule must be set\n at com.example.dagger.components.DaggerAppComponent$TabsActivitySubcomponentBuilder.build(DaggerAppComponent.java:116)\n at com.example.dagger.components.DaggerAppComponent$TabsActivitySubcomponentBuilder.build(DaggerAppComponent.java:106)\n at dagger.android.AndroidInjector$Builder.create(AndroidInjector.java:68)\n at dagger.android.DispatchingAndroidInjector.maybeInject(DispatchingAndroidInjector.java:79)\n at     dagger.android.DispatchingAndroidInjector.inject(DispatchingAndroidInjector.java:104)\n at dagger.android.AndroidInjection.inject(AndroidInjection.java:61)\n at com.example.base.BaseActivity.onCreate(BaseActivity.java:35)\n at com.example.ui.TabsActivity.onCreate(TabsActivity.java:13)\n at android.app.Activity.performCreate(Activity.java:6679)\n at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)\n at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2633)\n at     android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2741)\xc2\xa0\n at android.app.ActivityThread.-wrap12(ActivityThread.java)\xc2\xa0\n at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1488)\xc2\xa0\n at android.os.Handler.dispatchMessage(Handler.java:102)\xc2\xa0\n at android.os.Looper.loop(Looper.java:154)\xc2\xa0\n at android.app.ActivityThread.main(ActivityThread.java:6169)\xc2\xa0\n at java.lang.reflect.Method.invoke(Native Method)\xc2\xa0\n at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:888)\xc2\xa0\n at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:778)\xc2\xa0\n
Run Code Online (Sandbox Code Playgroud)\n\n

看完这个之后,我发现我只是忘记设置一些新的模块实例。但是,我不这样做,因为 @ContributesAndroidInjector 为我做这件事。\n好吧,当我查看生成的代码时,我发现TabsActivitySubcomponentBuilder没有 TabsActivityModule 的设置器。

\n\n
private final class TabsActivitySubcomponentBuilder\n  extends InjectorsModule_TabsActivityInjector.TabsActivitySubcomponent.Builder {\n    private TabsActivityModule tabsActivityModule;\n\nprivate TabsActivity seedInstance;\n\n@Override\npublic InjectorsModule_TabsActivityInjector.TabsActivitySubcomponent build() {\n  if (tabsActivityModule == null) {\n// Exceptions throws here\n        throw new IllegalStateException(\n            TabsActivityModule.class.getCanonicalName() + " must be set");\n      }\n      if (seedInstance == null) {\n        throw new IllegalStateException(TabsActivity.class.getCanonicalName() + " must be set");\n      }\n      return new TabsActivitySubcomponentImpl(this);\n    }\n\n    // here we seeing setter for activity\n    @Override\n    public void seedInstance(TabsActivity arg0) {\n      this.seedInstance = Preconditions.checkNotNull(arg0);\n    }\n\n   // and for module??\n  }\n
Run Code Online (Sandbox Code Playgroud)\n\n

最后,AndroidInjector.Builder仅设置活动实例:

\n\n
abstract class Builder<T> implements AndroidInjector.Factory<T> {\n    @Override\n    public final AndroidInjector<T> create(T instance) {\n// here\n      seedInstance(instance);\n// and here must be seedModule(module), but nothing\n      return build();\n    }\n\n    /**\n     * Provides {@code instance} to be used in the binding graph of the built {@link\n     * AndroidInjector}. By default, this is used as a {@link BindsInstance} method, but it may be\n     * overridden to provide any modules which need a reference to the activity.\n     *\n     * <p>This should be the same instance that will be passed to {@link #inject(Object)}.\n     */\n    @BindsInstance\n    public abstract void seedInstance(T instance);\n\n    /** Returns a newly-constructed {@link AndroidInjector}. */\n    public abstract AndroidInjector<T> build();\n  }\n
Run Code Online (Sandbox Code Playgroud)\n\n

也许我不明白什么?\n谢谢!

\n

edw*_*ock 5

好吧,经过一些研究和官方 dagger repo 的帮助后,我找到了解决方案:所有子组件抽象模块必须仅提供静态@Provides方法,或者仅使用构造函数注入,因为无法设置模块实例。