2017-09-08 125 views
0

我正在嘗試將活動依賴注入到片段展示器中。 應用程序結構非常簡單。ContributesAndroidInjector模塊必須設置

TabsActivity - viewpager

- TabFragment - 頁面項目

- [...]

TabsActivity顯示視圖 TabsActivityModule - 提供FragmentManager (例如)和一些東西TabsActivity

TabFragmentModule提供工具和TabFragment。 每個TabFragment擁有自己的演示者演示者注入TabActivityModule依賴關係。

在我的情況 - 演示注入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); 
} 

這裏是機器人視圖貢獻者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

好了,從官方的匕首回購一些研究和幫助後,我找到了解決辦法:所有子抽象模型必須只提供靜態@Provides方法,或者只是使用構造器注入,因爲沒有辦法設置模塊實例。