关于android:error:[Dagger / IncompatibleScopedBindings](无作用域)可能未引用作用域绑定:

error: [Dagger/IncompatiblyScopedBindings] (unscoped) may not reference scoped bindings:

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

error: [Dagger/IncompatiblyScopedBindings]
di.component.ApplicationComponent (unscoped) may not reference scoped
bindings: @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 repository.WalletRepositoryInterface
di.Module.WalletRepositoryModule.getWalletRepository(repository.SharedPreferencesHelper,
service.KeyStoreService)

这是我的ApplicationComponent类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@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的常规作用域。这是我的应用程序代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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)我没有这个问题,它仅在添加片段之后出现?如果任何人都可以帮助回答这个问题,那么仍然值得接受该回答,以帮助可能遇到此问题并希望了解此问题的其他任何人。


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

1
2
3
4
@Provides @ApplicationContext @ApplicationScope
Context getApplicationContext(MyApplication application) {
  return application.getApplicationContext();
}

您已经用@ApplicationScope注释了此@Provides方法,该方法指示Dagger将返回的上下文保存在Componenta中,具体来说,您还用@ApplicationScope进行了注释。在进行编辑更改之前,没有匹配的@ApplicationScope,Dagger给出了该信息。现在您已经有了一个,Dagger知道了将保存的Context实例存储在哪里。

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

另请参阅《 Dagger用户指南》:

Since Dagger 2 associates scoped instances in the graph with instances of component implementations, the components themselves need to declare which scope they intend to represent. For example, it wouldna€?t make any sense to have a @Singleton binding and a @RequestScoped binding in the same component because those scopes have different lifecycles and thus must live in components with different lifecycles. To declare that a component is associated with a given scope, simply apply the scope annotation to the component interface.

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

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