我正在嘗試將活動依賴注入到片段展示器中。 應用程序結構非常簡單。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();
}
也許我不懂的東西? 謝謝!