java - Dagger 2 : no injector factory bound for fragment

标签 java android dagger-2

我正在尝试将我正在构建的项目转换为将 dagger-android API 用于 DI 框架,但是在尝试使用 @ContributesAnroidInjector 注入(inject) fragment 时,我遇到了 IllegalArgumentException 的死胡同。

相关模块和组件如下:

应用程序组件.java

@Singleton
@Component(modules = {AndroidSupportInjectionModule.class,
    ApplicationModule.class,
    ActivityBindingModule.class,
    DataManagerModule.class})
public interface ApplicationComponent extends AndroidInjector<MyApplication> {

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 仅依赖于它们各自的演示者,而 dagger 在这些演示者中工作正常。但是我的 MainActivity 可以包含许多 fragment ,并在尝试使用以下方法注入(inject)其中一个 fragment 时导致崩溃:

HomeFragment.java
public class HomeFragment extends Fragment {
    ....
    @Override
    public void onAttach(Context context) {
        AndroidSupportInjection.inject(this);
        super.onAttach(context);
    }
    ....
}

这是我这次崩溃的日志:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.myapp/com.myapp.main.MainActivity}: java.lang.IllegalArgumentException: No injector factory bound for Class<com.myapp.ui.main.Home.HomeFragment>
at 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<com.myapp.ui.main.Home.HomeFragment>
        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 的绑定(bind)移动到 ActivityBindingModule,应用程序运行良好,但如果我将这些绑定(bind)带回 MainActivityModule,则崩溃会再次出现。我在这里做错了什么?

编辑:
public class MyApp extends DaggerApplication {

    @Override
    protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
        return DaggerApplicationComponent.builder().application(this).build();
    }
}

和我的主要 Activity :
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
}

最佳答案

当您使用 AndroidSupportInjection.inject(this) 注入(inject)时来自您的HomeFragment , Dagger 将遍历父 fragment 层次结构找到实现 HasSupportFragmentInjector 的人.为了让它工作,让你的MainActivity扩展 DaggerAppCompatActivity实现HasSupportFragmentInjector .

来自 AndroidSupportInjection.inject(Fragment fragment) 的文档:

Injects {@code fragment} if an associated {@link dagger.android.AndroidInjector} implementation can be found, otherwise throws an {@link IllegalArgumentException}.

Uses the following algorithm to find the appropriate {@code AndroidInjector} to use to inject {@code fragment}:

  1. Walks the parent-fragment hierarchy to find the a fragment that implements {@link HasSupportFragmentInjector}, and if none do
  2. Uses the {@code fragment}'s {@link Fragment#getActivity() activity} if it implements {@link HasSupportFragmentInjector}, and if not
  3. Uses the {@link android.app.Application} if it implements {@link HasSupportFragmentInjector}.

If none of them implement {@link HasSupportFragmentInjector}, a {@link IllegalArgumentException} is thrown.

@throws IllegalArgumentException if no parent fragment, activity, or application implements {@link HasSupportFragmentInjector}.



有了这个,Dagger 将使用
@FragmentScope
@ContributesAndroidInjector
abstract HomeFragment provideHomeFragment();

来自您的MainActivityModule注入(inject)你的HomeFragment .

关于java - Dagger 2 : no injector factory bound for fragment,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61822251/

相关文章:

java - 递归程序执行期间出现 Truffle 语言运行时错误

java - 在 Java 中将 sqlite 从磁盘备份和恢复到内存

android - 按钮菜单安卓

android - 具有不同范围的模块

firebase - Dagger 2 @Inject 上的空引用

android - 如何使用 dagger2 注入(inject)没有任何 Activity 或 fragment 的 java 类

java - Log4j2 json 配置不写入文件

java - 将 Java UUID 作为字节发送到 C++,然后通过 TCP 返回

android - 如果用户有使用 firebase 的互联网连接,请在线检查用户

android - 如何防止在 Android 中调整图像大小