当前位置: 首页 > 面试题库 >

Dagger2:没有注射器工厂绑定碎片

公孙涵育
2023-03-14
问题内容

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

相关模块和组件如下:

ApplicationComponent.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可能包含许多片段,并在尝试使用以下片段之一注入这些片段时导致崩溃:

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的绑定移动到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
}

问题答案:

当您AndroidSupportInjection.inject(this)从中注入时HomeFragment,Dagger将遍历父片段层次结构以找到实现的人HasSupportFragmentInjector。要使其工作,请使您的MainActivity扩展DaggerAppCompatActivity实现HasSupportFragmentInjector

从文档AndroidSupportInjection.inject(Fragment fragment)

如果可以找到关联的{@link
dagger.android.AndroidInjector}实现,则注入{@codefragment},否则抛出{@link
IllegalArgumentException}。

使用以下算法找到合适的{@code AndroidInjector}来注入{@codefragment}:

  1. 遍历父片段层次结构以找到实现{@link HasSupportFragmentInjector}的片段,如果没有,则执行
  2. 如果实现了{@link HasSupportFragmentInjector},则使用{@codefragment}的{@link
    Fragment#getActivity()活动},否则执行
  3. 如果实现了{@link HasSupportFragmentInjector},则使用{@link
    android.app.Application}。

如果它们都不实现{@link HasSupportFragmentInjector},则抛出{@link
IllegalArgumentException}。

如果没有父片段,活动或应用程序没有实现{@link HasSupportFragmentInjector},则@throws
IllegalArgumentException。

有了这个,匕首将使用

@FragmentScope
@ContributesAndroidInjector
abstract HomeFragment provideHomeFragment();

从你的MainActivityModule内心注入HomeFragment



 类似资料:
  • 我不熟悉匕首2。我有两个活动,我想使用注入的ViewModel。这是我的ViewModuleFactory: 我的ViewModel模块: 用于映射的我的ViewModelKey: 我的活动模块: 我的AppModule: 我的AppComponent: 我的申请: 在活动中: 它正在注入时引发异常: 有人能帮我识别代码中的问题吗? ................................

  • 我有两个服务类和一个存储库类。当我尝试将一个服务bean自动连接到另一个服务bean时,一个bean会被注入。但是当我尝试调用该方法时,它会显示。请帮帮我。过去3天我一直坚持这样做。 我的第一堂服务课: 我的第二个服务类别: 我的存储库类: 我已经尝试了一切(例如

  • 假设有一个类A,它的构造函数是这样的: 还有AFactory: 所以要创建一个A的实例,我显然需要做这样的事情: 但是,假设我有其他类:例如,B类、C类和D类具有类型为A的成员(带有字段注入,但也可以是ctor): 我希望将 A 的相同实例注入到这些类中。但仍然可以选择将 A 的另一个实例注入其他类(假设 E 类和 F 类)。 正确的做法是什么?我就是想不出一个干净的方法来做到这一点。

  • 将@Singleton直接应用于包含@PostConstruct和@Transactional的服务类按预期工作 - 调用@PostConstruct并且事务方法工作正常。 将bean定义移动到如下所示的@Factory中仍然有效,MyService singleton仍然被创建,但没有得到增强-@PostConstruct未被调用,事务方法将无法工作(无法获取当前线程的事务同步会话) 与Spri

  • 问题内容: 我有一个变量,将由一个或多个控制器使用,由服务更改。在那种情况下,我建立了一个服务来将该变量保存在内存中,并在控制器之间共享。 问题是:每次变量更改时,控制器中的变量都不会实时更新。 我创建这个小提琴来提供帮助。http://jsfiddle.net/ncyVK/ -–请注意,当我增加count的值时,或永远不会更新。 如何将Service / Factory变量绑定到Controll

  • 我在实施辅助注射时遇到了错误。 辅助注射一直有效,直到我引入了另一个名为管理器的类,它依赖于辅助类。经理想要使用代码在构建喷油器图时中断。它没有更进一步。 直觉上,我理解当对象A得到帮助时,那么B(依赖于A)实际上也通过A得到了隐含的帮助。 请注意,我检查过了。我想像ColinD这样的人肯定知道答案如何使用Guice的AssistedInject?如何将辅助注入类绑定到接口? 出于好奇,有没有好的