必须设置ContributesAndroidInjector模块

时间:2017-09-08 18:06:29

标签: android dagger-2

我正在尝试将活动依赖项注入片段演示者。 应用程序结构非常简单。

TabsActivity - viewpager

- TabFragment - 页面项

- [...]

TabsActivity 显示视图 TabsActivityModule - 提供 FragmentManager (例如)和 TabsActivity

的一些内容

TabFragmentModule 提供 TabFragment 的内容。 每个 TabFragment 都有自己的 Presenter Presenter 会注入 TabActivityModule 依赖项。

在我的情况下 - Presenter注入 FragmentManager

这是代码:

应用程序类

class App extends Application implements HasActivityInjector {
    @Inject
    DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;

    @Override
    public AndroidInjector<Activity> activityInjector() {
        return dispatchingAndroidInjector;
    }
   /*
   blah blah creating app component onCreate() ...
       DaggerAppComponent
            .builder()
            .context(this)
            .build()
            .inject(this);
   */ 
}

根应用程序组件

@Singleton
@Component(modules = {InjectorsModule.class})
public interface AppComponent {

    @Component.Builder
    interface Builder {
        @BindsInstance
        Builder context(Context context);

        AppComponent build();
    }

    void inject(App app);
}

这是android视图贡献者 InjectorsModule

@Module(includes = {AndroidSupportInjectionModule.class})
public abstract class InjectorsModule {

    @ActivityScope
    @ContributesAndroidInjector(modules = {TabsActivityModule.class})
    abstract TabsActivity tabsActivityInjector();
}

活动 TabsActivityModule

@Module
public abstract class TabsActivityModule {

    @Provides
    @ActivityScope
    public FragmentManager provideFragmentManager(TabsActivity activity) {
        return activity.getFragmentManager();
    }

    @Provides @Named("activity")
    @ActivityScope
    public Context provideActivityContext(TabsActivity activity) {
        return activity;
    }

    // Here contributes tab fragment
    @FragmentScope
    @ContributesAndroidInjector(modules = {TabFragmentModule.class})
    public abstract TabFragment tabFragment();
}

片段 TabFragmentModule

@Module
public abstract class TabFragmentModule {
    @Provides @Named("answer")
    @FragmentScope
    public int provideSomeInt() {
        return 42;
    }
}

最后,仅举例来说 - TabPresenter

public class TabPresenter {
    @Inject @Named("answer") int mAnswer;
    @Inject @Named("activity") mActivityContext;
    @Inject FragmentManager mFragmentManager;

    @Inject
    public TabPresenter() {}

    public void doNothingWithAnswerAndContextAndFragmentManager() {
        mAnswer *= 1;
    }
}

在此之后,构建完成并成功。但是在运行时,我在片段注入时立即得到InvalidStateException:

onAttach(Activity activity) {
    AndroidInjection.inject(this);
    super.onAttach(activity);
} 

异常堆栈跟踪:

FATAL EXCEPTION: main
Process: com.example.drive.dagger2new, PID: 3064
 java.lang.RuntimeException: 
Unable to start activity 
ComponentInfo{com.example.drive.dagger2new/com.example.ui.TabsActivity}:
java.lang.IllegalStateException:
com.example.dagger.modules.main.TabsActivityModule must be set

 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2680)
 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2741)
 at android.app.ActivityThread.-wrap12(ActivityThread.java)
 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1488)
 at android.os.Handler.dispatchMessage(Handler.java:102)
 at android.os.Looper.loop(Looper.java:154)
 at android.app.ActivityThread.main(ActivityThread.java:6169)
 at java.lang.reflect.Method.invoke(Native Method)
 at     com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:888)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:778)

Caused by: java.lang.IllegalStateException: com.example.dagger.modules.main.TabsActivityModule must be set
 at com.example.dagger.components.DaggerAppComponent$TabsActivitySubcomponentBuilder.build(DaggerAppComponent.java:116)
 at com.example.dagger.components.DaggerAppComponent$TabsActivitySubcomponentBuilder.build(DaggerAppComponent.java:106)
 at dagger.android.AndroidInjector$Builder.create(AndroidInjector.java:68)
 at dagger.android.DispatchingAndroidInjector.maybeInject(DispatchingAndroidInjector.java:79)
 at     dagger.android.DispatchingAndroidInjector.inject(DispatchingAndroidInjector.java:104)
 at dagger.android.AndroidInjection.inject(AndroidInjection.java:61)
 at com.example.base.BaseActivity.onCreate(BaseActivity.java:35)
 at com.example.ui.TabsActivity.onCreate(TabsActivity.java:13)
 at android.app.Activity.performCreate(Activity.java:6679)
 at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2633)
 at     android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2741) 
 at android.app.ActivityThread.-wrap12(ActivityThread.java) 
 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1488) 
 at android.os.Handler.dispatchMessage(Handler.java:102) 
 at android.os.Looper.loop(Looper.java:154) 
 at android.app.ActivityThread.main(ActivityThread.java:6169) 
 at java.lang.reflect.Method.invoke(Native Method) 
 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:888) 
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:778) 

看了这个,但是,我只是忘了设置一些新的模块实例。但是,我不这样做,因为@ContributesAndroidInjector为我做了。 好的,当我查看生成的代码时,我看到 TabsActivitySubcomponentBuilder 没有TabsActivityModule的setter。

private final class TabsActivitySubcomponentBuilder
  extends InjectorsModule_TabsActivityInjector.TabsActivitySubcomponent.Builder {
    private TabsActivityModule tabsActivityModule;

private TabsActivity seedInstance;

@Override
public InjectorsModule_TabsActivityInjector.TabsActivitySubcomponent build() {
  if (tabsActivityModule == null) {
// Exceptions throws here
        throw new IllegalStateException(
            TabsActivityModule.class.getCanonicalName() + " must be set");
      }
      if (seedInstance == null) {
        throw new IllegalStateException(TabsActivity.class.getCanonicalName() + " must be set");
      }
      return new TabsActivitySubcomponentImpl(this);
    }

    // here we seeing setter for activity
    @Override
    public void seedInstance(TabsActivity arg0) {
      this.seedInstance = Preconditions.checkNotNull(arg0);
    }

   // and for module??
  }

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

abstract class Builder<T> implements AndroidInjector.Factory<T> {
    @Override
    public final AndroidInjector<T> create(T instance) {
// here
      seedInstance(instance);
// and here must be seedModule(module), but nothing
      return build();
    }

    /**
     * Provides {@code instance} to be used in the binding graph of the built {@link
     * AndroidInjector}. By default, this is used as a {@link BindsInstance} method, but it may be
     * overridden to provide any modules which need a reference to the activity.
     *
     * <p>This should be the same instance that will be passed to {@link #inject(Object)}.
     */
    @BindsInstance
    public abstract void seedInstance(T instance);

    /** Returns a newly-constructed {@link AndroidInjector}. */
    public abstract AndroidInjector<T> build();
  }

也许我不懂东西? 谢谢!

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:0)

我有同样的错误,经过研究我发现错误导入模块 导入是这样的

import com.google.android.datatransport.runtime.dagger.Module

但应该是

import dagger.Module