匕首 2 错误子组件可能不引用作用域绑定



我在我的应用程序中使用Dagger2来提供依赖项。我在构建应用程序时收到以下错误。

e: /Users/sriramr/Desktop/android/Movie/MovieInfo/app/build/generated/source/kapt/debug/in/sriram/movieinfo/di/ActivityBuilder_BindMoviesListActivity.java:22: error: in.sriram.movieinfo.di.ActivityBuilder_BindMoviesListActivity.MoviesListActivitySubcomponent (unscoped) may not reference scoped bindings:
@Subcomponent(modules = MoviesListActivityModule.class)
^
@Provides @Singleton in.sriram.movieinfo.network.TmdbService in.sriram.movieinfo.di.MoviesListActivityModule.getTmdbService(retrofit2.Retrofit)
@Provides @Singleton retrofit2.Retrofit in.sriram.movieinfo.di.NetworkModule.getRetrofit(okhttp3.OkHttpClient, retrofit2.converter.gson.GsonConverterFactory, retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory)
@Provides @Singleton okhttp3.OkHttpClient in.sriram.movieinfo.di.NetworkModule.getOkHttpClient(okhttp3.logging.HttpLoggingInterceptor, okhttp3.Cache)
@Provides @Singleton okhttp3.logging.HttpLoggingInterceptor in.sriram.movieinfo.di.NetworkModule.getHttpLoggingInterceptor()
@Provides @Singleton okhttp3.Cache in.sriram.movieinfo.di.NetworkModule.getCacheFile(@Named("application-context") android.content.Context)
@Provides @Singleton retrofit2.converter.gson.GsonConverterFactory in.sriram.movieinfo.di.NetworkModule.getGsonConverterFactory()
@Provides @Singleton retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory in.sriram.movieinfo.di.NetworkModule.getRxJavaFactory()
@Provides @Singleton in.sriram.movieinfo.cache.AppDatabase in.sriram.movieinfo.di.ContextModule.getAppDatabase(@Named("application-context") android.content.Context)
@Provides @Singleton com.squareup.picasso.Picasso in.sriram.movieinfo.di.MoviesListActivityModule.getPicasso(@Named("application-context") android.content.Context)

这是我的ContextModule

@Module
public class ContextModule {
@Provides
@Named("application-context")
Context getContext(Application app) {
return app;
}
@Provides
@Singleton
AppDatabase getAppDatabase(@Named("application-context") Context context) {
return Room.databaseBuilder(context,
AppDatabase.class, "database-name").build();
}
}

这是我的NetworkModule

@Module(includes = ContextModule.class)
public class NetworkModule {
@Provides
@Singleton
Cache getCacheFile(@Named("application-context") Context context) {
File cacheFile = new File(context.getCacheDir(), "moviedb-cache");
return new Cache(cacheFile, 10 * 1000 * 1000);
}
@Provides
@Singleton
OkHttp3Downloader getOkHttp3Downloader(OkHttpClient okHttpClient) {
return new OkHttp3Downloader(okHttpClient);
}
@Provides
@Singleton
OkHttpClient getOkHttpClient(HttpLoggingInterceptor loggingInterceptor, Cache cache) {
return new OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.cache(cache)
.build();
}
@Provides
@Singleton
Retrofit getRetrofit(OkHttpClient client, GsonConverterFactory gsonConverterFactory, RxJava2CallAdapterFactory callAdapter) {
return new Retrofit.Builder()
.addConverterFactory(gsonConverterFactory)
.addCallAdapterFactory(callAdapter)
.baseUrl("https://api.themoviedb.org/3/")
.client(client)
.build();
}
@Provides
@Singleton
HttpLoggingInterceptor getHttpLoggingInterceptor() {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(message -> Timber.tag("OkHttp").d(message));
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
return loggingInterceptor;
}

@Provides
@Singleton
GsonConverterFactory getGsonConverterFactory() {
return GsonConverterFactory.create();
}
@Provides
@Singleton
RxJava2CallAdapterFactory getRxJavaFactory() {
return RxJava2CallAdapterFactory.create();
}
}

最后是MovieListActivityModule

@Module(includes = NetworkModule.class)
public class MoviesListActivityModule {
@Provides
@Singleton
TmdbService getTmdbService(Retrofit retrofit) {
return retrofit.create(TmdbService.class);
}
@Provides
@Singleton
Picasso getPicasso(@Named("application-context") Context context) {
return new Picasso.Builder(context)
.loggingEnabled(true)
.build();
}
}

这是ActivityBuilder

@Module
public abstract class ActivityBuilder {
@ContributesAndroidInjector(modules = MoviesListActivityModule.class)
abstract MoviesListActivity bindMoviesListActivity();
}

最后是应用程序组件

@Singleton
@Component(modules = {AndroidInjectionModule.class, ContextModule.class, ActivityBuilder.class})
public interface AppComponent {
@Component.Builder
interface Builder {
@BindsInstance
Builder application(Application application);
AppComponent build();
}
void inject(MovieInfoApp app);
}

我是dagger 2 的新手,我从 Medium 的随机教程中学习了这一点。

我在这里看不到任何子组件。我知道子组件已生成。

此错误仅发生在@Singleton作用域依赖项上。

我遵循了一些堆栈溢出链接,并向 AppComponent 接口添加了@Singleton

我该如何解决这个问题?

将 MoviesListActivityModule 重命名为 MoviesListApplicationModule,将其从@ContributesAndroidInjector中删除,并将其放入 AppComponent 的modules列表中。


在幕后,@ContributesAndroidInjector会生成特定于您的 MoviesListActivity 的@Subcomponent。当您尝试使用AndroidInjection.inject(Activity)注入 MoviesListActivity 时,Dagger 会创建一个子组件实例,该实例包含 MoviesListActivity 的 MembersInjector(知道如何填充 MoviesListActivity 中所有@Inject字段的生成代码)以及您的 Activity(或其依赖项)可能需要的任何作用域绑定。这是您缺少的组件,它以模块命名,@ContributesAndroidInjector方法名称ActivityBuilder_BindMoviesListActivity.MoviesListActivitySubcomponent

您可以将作用域(如您创建的@ActivityScope)添加到@ContributesAndroidInjector,dagger.android 会将它们添加到生成的子组件中,就像设置modules = {/*...*/}会将模块添加到其中一样。但是,这不是您的问题。

首先,您向AppComponent添加@Singleton是正确的;这是一件非常普遍的事情,在这里这样做是正确的。添加@Singleton意味着 Dagger 将自动注意标有@Singleton的绑定,并以相同的方式将它们的副本保存在您注释的组件中。如果要创建@ActivityScope注释并将其添加到子组件中,Dagger 将注意用@ActivityScope注释的绑定,并从同一 Activity 实例中返回相同的实例,但与相同 Activity或其他 Activity 类型的其他实例相比,返回不同的实例

您的问题是您将@Singleton范围的绑定 Picasso 和 TmdbService添加到无作用域的子组件图中。你告诉Dagger的是,在你的应用程序组件(不是你的活动,你的应用程序)的整个生命周期中,你应该始终返回相同的Picasso和TmdbService实例。但是,通过在子组件的模块列表而不是顶级@Singleton @Component上进行绑定,您可以在 Dagger 尝试配置活动级绑定时告知它这些应用程序级对象。这同样适用于 NetworkModule 中的绑定,这些绑定也列在错误消息中。

移动模块后,您将始终收到相同的 Picasso、TmdbService、OkHttpClient 和所有其他实例,这应该允许这些对象帮助管理缓存、批处理和动态请求,而不必担心您正在与哪个实例进行交互。在应用的整个生命周期中,它将始终是相同的实例。

最新更新