我正在尝试将我正在构建的项目转换为使用dagger-android API用于DI框架,但是当尝试使用@ContributesAnroidInjector注入片段时,我遇到了IllegalArgumentException的死胡同.
相关模块和组件包括在下面:
ApplicationComponent.java
@Singleton @Component(modules = {AndroidSupportInjectionModule.class, ApplicationModule.class, ActivityBindingModule.class, DataManagerModule.class}) public interface ApplicationComponent extends AndroidInjector{ DataManagerContract getDataManager(); void inject(MyApplication application); @Component.Builder interface Builder { @BindsInstance ApplicationComponent.Builder application(Application application); ApplicationComponent build(); } }
我的ActivityBindingModule.java:
@Module public abstract class ActivityBindingModule { @ActivityScope @ContributesAndroidInjector(modules = MainActivityModule.class) abstract MainActivity bindMainActivity(); @ActivityScope @ContributesAndroidInjector(modules = SplashActivityModule.class) abstract SplashActivity bindSplashActivity(); @ActivityScope @ContributesAndroidInjector(modules = LoginActivityModule.class) abstract LoginActivity bindLoginActivity(); }
MainActivityModule.java
@Module public abstract class MainActivityModule { @ActivityScope @Binds abstract MainActivityContract.Presenter provideMainActivityPresenter(MainActivityPresenter presenter); @FragmentScope @ContributesAndroidInjector abstract HomeFragment provideHomeFragment(); @FragmentScope @Binds abstract HomeFragmentContract.Presenter provideHomeFragmentPresenter(HomeFragmentPresenter presenter); // Inject other fragments and presenters }
SplashActivity和LoginActivity仅取决于他们各自的演示者,并且匕首在这些方面工作得很好.但是我的MainActivity可以包含许多片段,并在尝试使用以下方法注入其中一个片段时导致崩溃:
HomeFragment.java
public class HomeFragment extends Fragment { .... @Override public void onAttach(Context context) { AndroidSupportInjection.inject(this); super.onAttach(context); } .... }
这是我崩溃的logcat:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.myapp/com.myapp.main.MainActivity}: java.lang.IllegalArgumentException: No injector factory bound for Classat android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) at android.app.ActivityThread.-wrap12(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6119) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) Caused by: java.lang.IllegalArgumentException: No injector factory bound for Class at dagger.android.DispatchingAndroidInjector.inject(DispatchingAndroidInjector.java:104) at dagger.android.support.AndroidSupportInjection.inject(AndroidSupportInjection.java:74) at com.myapp.ui.main.Home.HomeFragment.onAttach(HomeFragment.java:65) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1363) at android.support.v4.app.FragmentTransition.addToFirstInLastOut(FragmentTransition.java:1109) at android.support.v4.app.FragmentTransition.calculateFragments(FragmentTransition.java:996) at android.support.v4.app.FragmentTransition.startTransitions(FragmentTransition.java:99) at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2364) at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2322) at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2229) at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3221) at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3171) at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:192) at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:560) at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:177) at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1248) at android.app.Activity.performStart(Activity.java:6696) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2628) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) at android.app.ActivityThread.-wrap12(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6119) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
我不确定代码中的问题在哪里.如果我将HomeFragment的绑定移动到ActivityBindingModule,应用程序运行正常,但如果我将这些绑定带回MainActivityModule,则会发生崩溃.我在这做错了什么?
编辑:
public class MyApp extends DaggerApplication { @Override protected AndroidInjector extends DaggerApplication> applicationInjector() { return DaggerApplicationComponent.builder().application(this).build(); } }
和我的主要活动:
public class MainActivity extends AppCompatActivity implements MainActivityContract.View, NavigationView.OnNavigationItemSelectedListener { @Inject MainActivityContract.Presenter mPresenter; @Override protected void onCreate(Bundle savedInstanceState) { AndroidInjection.inject(this); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Open home fragment on first start if (savedInstanceState == null) { // Create new instance of HomeFragment HomeFragment homeFragment = HomeFragment.newInstance(); FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); fragmentTransaction.replace(R.id.content_main, homeFragment) .commit(); } // Other logic }
Benjamin.. 23
当您AndroidSupportInjection.inject(this)
从中注入使用时HomeFragment
,Dagger将遍历父片段层次结构以找到实现的人HasSupportFragmentInjector
.为了使它工作,使你的MainActivity
扩展DaggerAppCompatActivity
实现HasSupportFragmentInjector
.
来自以下文件AndroidSupportInjection.inject(Fragment fragment)
:
如果可以找到关联的{@link dagger.android.AndroidInjector}实现,则注入{@code fragment},否则抛出{@link IllegalArgumentException}.
使用以下算法查找用于注入{@code fragment}的相应{@code AndroidInjector}:
遍历父片段层次结构以查找实现{@link HasSupportFragmentInjector}的片段,如果没有,则执行
如果它实现{@link HasSupportFragmentInjector},则使用{@code fragment}的{@link Fragment#getActivity()activity},如果没有
如果它实现了{@link HasSupportFragmentInjector},则使用{@link android.app.Application}.
如果它们都没有实现{@link HasSupportFragmentInjector},则抛出{@link IllegalArgumentException}.
@throws IllegalArgumentException如果没有父片段,活动或应用程序实现{@link HasSupportFragmentInjector}.
有了这个,Dagger就会使用
@FragmentScope @ContributesAndroidInjector abstract HomeFragment provideHomeFragment();
从你MainActivityModule
注入你的内心HomeFragment
.
当您AndroidSupportInjection.inject(this)
从中注入使用时HomeFragment
,Dagger将遍历父片段层次结构以找到实现的人HasSupportFragmentInjector
.为了使它工作,使你的MainActivity
扩展DaggerAppCompatActivity
实现HasSupportFragmentInjector
.
来自以下文件AndroidSupportInjection.inject(Fragment fragment)
:
如果可以找到关联的{@link dagger.android.AndroidInjector}实现,则注入{@code fragment},否则抛出{@link IllegalArgumentException}.
使用以下算法查找用于注入{@code fragment}的相应{@code AndroidInjector}:
遍历父片段层次结构以查找实现{@link HasSupportFragmentInjector}的片段,如果没有,则执行
如果它实现{@link HasSupportFragmentInjector},则使用{@code fragment}的{@link Fragment#getActivity()activity},如果没有
如果它实现了{@link HasSupportFragmentInjector},则使用{@link android.app.Application}.
如果它们都没有实现{@link HasSupportFragmentInjector},则抛出{@link IllegalArgumentException}.
@throws IllegalArgumentException如果没有父片段,活动或应用程序实现{@link HasSupportFragmentInjector}.
有了这个,Dagger就会使用
@FragmentScope @ContributesAndroidInjector abstract HomeFragment provideHomeFragment();
从你MainActivityModule
注入你的内心HomeFragment
.