【问题标题】:error: [Dagger/IncompatiblyScopedBindings] (unscoped) may not reference scoped bindings:错误:[Dagger/IncompatiblyScopedBindings](无作用域)可能不引用作用域绑定:
【发布时间】:2018-12-20 21:31:02
【问题描述】:

我不明白如何解决此错误。在尝试将片段添加到我的应用程序并使用 Dagger for DI 后出现此错误。这是错误堆栈:

错误:[Dagger/IncompatiblyScopedBindings] di.component.ApplicationComponent (unscoped) 可能不引用 scoped 绑定:@Provides @di.ApplicationContext @di.ApplicationScope android.content.Context di.Module.ApplicationContextModule.getApplicationContext(application.MyApplication) @Provides @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() @Provides @di.ApplicationScope service.CoinmarketcapService di.Module.CoinmarketcapModule.getCoinmarketcapService(com.google.gson.Gson, okhttp3.OkHttpClient) @Provides @di.ApplicationScope com.google.gson.Gson di.Module.GsonModule.getGson() @Provides @di.ApplicationScope okhttp3.OkHttpClient di.Module.OkHttpModule.getOkHttpClient() @Provides @di.ApplicationScope 存储库.WalletRepositoryInterface di.Module.WalletRepositoryModule.getWalletRepository(repository.SharedPreferencesHelper, 服务.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)我没有这个问题,它只是在添加片段后才出现?如果有人可以帮助回答这个问题,那么仍然值得接受这个答案来帮助其他可能有这个问题并想要理解它的人。

【问题讨论】:

    标签: android dependency-injection dagger-2 dagger


    【解决方案1】:

    您没有向我们展示 ApplicationContextModule,但从您的错误消息来看,它可能包含以下内容:

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

    你已经用@ApplicationScope 注释了这个@Provides 方法,它指示Dagger 将返回的上下文保存在一个组件中——特别是你也用@ApplicationScope 注释的组件。在您对编辑进行更改之前,没有匹配的 @ApplicationScope,并且 Dagger 给了您该消息。现在你有了一个,Dagger 知道在哪里存储保存的 Context 实例。

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

    另见Dagger User's Guide

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

    值得注意的是,由于 Application 的实例在组件的生命周期内也不会改变,并且 getApplicationContext 的值预计不会在 Application 的生命周期内改变。这意味着除了避免重复调用 ApplicationContextModule 中的 your getApplicationContext 方法之外,您的作用域并没有真正给您太多。


    “但是等等,”我听到你的想法。 “为什么 Dagger 不知道我的 @ApplicationScoped 绑定属于我的 ApplicationComponent?毕竟,Dagger 看到 ApplicationContextModule 安装在 ApplicationComponent 上,所以唯一有意义的方法是 ApplicationComponent 是否隐含 @ApplicationScoped 。”两个原因:首先,从某种意义上说,这是强制文档,它也有助于 Dagger 更清楚哪个绑定是错误的,因此您不会不小心直接在 ApplicationComponent 中安装 @ActivityScoped 绑定并让 Dagger 相信您的组件同时是应用程序-范围和活动范围。其次,您还可以使用范围注释来注释可注入类,而 Dagger 将无法推断出任何东西,因为它没有可以读取的组件-安装-模块关系。在这两者之间,Dagger 强制你在文档中注释你的组件,我在上面引用了。

    【讨论】:

    • 非常感谢您的回答!帮助更多地了解 Dagger 的幕后情况。另外,再次感谢,您对另一个问题的旧答案之一帮助我解决了另一个问题!
    【解决方案2】:

    我遇到了同样的问题,但是从 ApplicationComponent 中删除提供 Context 的模块后问题就消失了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多