错误:[Dagger / IncompatibleScopedBindings](无作用域)可能未引用作用域绑定:

时间:2018-12-20 21:31:03

标签: android dependency-injection dagger-2 dagger

我不知道如何解决此错误。尝试将片段添加到我的应用程序并使用Dagger进行DI后,出现了此错误。这是错误堆栈:

  

错误:[匕首/不兼容范围绑定]   di.component.ApplicationComponent(无作用域)可能未引用作用域   绑定:@Provides @ di.ApplicationContext @ di.ApplicationScope   android.content.Context   di.Module.ApplicationContextModule.getApplicationContext(application.MyApplication)   @提供@ di.ApplicationScope android.content.SharedPreferences   di.Module.SharedPreferencesModule.getSharedPreferences(@ di.ApplicationContext   android.content.Context)@Provides @ di.ApplicationScope   service.KeyStoreServiceInterface   di.Module.KeyStoreModule.getKeyStoreService(@Named(“ KEY_STORE_FILE”)   java.io.File)@Provides @ di.ApplicationScope   repository.SharedPreferencesHelper   di.Module.SharedPreferenceHelperModule.getSharedPreferencesHelper()   @提供@ di.ApplicationScope service.CoinmarketcapService   di.Module.CoinmarketcapModule.getCoinmarketcapService(com.google.gson.Gson,   okhttp3.OkHttpClient)@提供@ di.ApplicationScope   com.google.gson.Gson di.Module.GsonModule.getGson()@Provides   @ di.ApplicationScope okhttp3.OkHttpClient   di.Module.OkHttpModule.getOkHttpClient()@提供   @ di.ApplicationScope存储库.WalletRepositoryInterface   di.Module.WalletRepositoryModule.getWalletRepository(repository.SharedPreferencesHelper,   service.KeyStoreService)

这是我的ApplicationComponent类:

@Component(modules = {ApplicationContextModule.class,
        SharedPreferencesModule.class,
        KeyStoreModule.class,
        SharedPreferenceHelperModule.class,
        AndroidInjectionModule.class,
        BindModule.class,
        AndroidSupportInjectionModule.class,
        OkHttpModule.class,
        GsonModule.class,
        CoinmarketcapModule.class,
        WalletRepositoryModule.class})
@SuppressWarnings("unchecked")
public interface ApplicationComponent {

    @Component.Builder
    interface Builder {
        @BindsInstance
        Builder application(MyApplication myApplication);
        ApplicationComponent build();
    }

    void inject(MyApplication myApplication);

    @ApplicationContext
    Context getApplicationContext();

    SharedPreferences getSharedPreferences();

    KeyStoreServiceInterface getKeyStoreService();

    SharedPreferencesHelper getSharedPreferencesHelper();

    CoinmarketcapService getCoinmarketcapService();

    WalletRepositoryInterface getWalletRepository();

}

我的android代码中有FragmentScope和ActivityScope注释。这只是带有Retention.RUNTIME的Dagger的常规作用域。这是我的应用程序代码:

public class MyApplication extends MultiDexApplication implements HasActivityInjector, HasFragmentInjector {

    private ApplicationComponent applicationComponent;

    @Inject
    DispatchingAndroidInjector<Activity> dispatchingActivityInjector;
    @Inject
    DispatchingAndroidInjector<Fragment> fragmentDispatchingAndroidInjector;

    @Override
    public void onCreate() {

        super.onCreate();

        DaggerApplicationComponent
                .builder()
                .application(this)
                .build()
                .inject(this);

        Timber.plant(new Timber.DebugTree());
    }

    @Override
    public AndroidInjector<Activity> activityInjector() {
        return dispatchingActivityInjector;
    }

    public ApplicationComponent getApplicationComponent() {
        return applicationComponent;
    }

    @Override
    public AndroidInjector<Fragment> fragmentInjector() {
        return fragmentDispatchingAndroidInjector;
    }
}

任何帮助将不胜感激。

编辑:我设法通过将@ApplicationScope添加到我的组件来解决此问题。为什么我必须这样做?在将片段和@FragmentScope添加到我的代码之前(在此之前,我只有@activityscope和@applicationscope)没有这个问题,它仅在添加片段之后出现?如果任何人都可以帮助回答这个问题,那么仍然值得接受该回答,以帮助可能遇到此问题并想了解它的任何其他人。

1 个答案:

答案 0 :(得分:1)

您尚未向我们显示ApplicationContextModule,但是从您的错误消息中可能包含以下内容:

@Provides @ApplicationContext @ApplicationScope
Context getApplicationContext(MyApplication application) {
  return application.getApplicationContext();
}

您已经用@Provides注释了此@ApplicationScope方法,该方法指示Dagger将返回的上下文保存在Component(特别是您也用@ApplicationScope注释的组件)中。在进行编辑更改之前,没有匹配的@ApplicationScope,Dagger给出了该信息。现在您已经有了一个,Dagger知道了将保存的Context实例存储在何处。

令人困惑的慷慨地,Dagger不会反对您尚未使用的不合适的绑定,因此Dagger不会反对您缺少组件范围注释,直到您开始在其中使用绑定作用域,这可能是在您引入Fragment作用域的同时发生的。

另请参阅Dagger User's Guide

  

由于Dagger 2将图中的范围内实例与组件实现实例相关联,因此组件本身需要声明它们打算代表的范围。例如,在同一组件中具有@Singleton绑定和@RequestScoped绑定没有任何意义,因为这些作用域具有不同的生命周期,因此必须存在于具有不同生命周期的组件中。要声明组件与给定范围相关联,只需将范围注释应用于组件接口。

值得注意的是,由于Application实例在组件的整个生命周期中也不会发生变化,并且getApplicationContext的值在Application的整个生命周期中也不会发生变化。这意味着除了避免重复调用ApplicationContextModule中的您的 getApplicationContext方法之外,您的范围实际上没有给您带来什么好处。


“等等,”我听到你在想。 “为什么Dagger不知道我的@ApplicationScoped绑定属于我的ApplicationComponent?毕竟,Dagger看到ApplicationContextModule安装在ApplicationComponent上,因此唯一有意义的方法是如果ApplicationComponent是隐式{ {1}}。”有两个原因:首先,从某种意义上讲,这是强制性的文档,它也可以帮助Dagger更加清楚哪个绑定是错误的,这样您就不会在偶然的情况下将@ApplicationScoped绑定直接安装到ApplicationComponent中并说服Dagger您的组件是同时存在的应用程序范围和活动范围。其次,您还可以使用范围注释对可注入类进行注释,并且Dagger无法推断任何内容,因为它没有可读取的组件-安装-模块关系。在这两者之间,Dagger迫使您在我上面引用的文档中注释组件。