Dagger2报错:@Component.Builder缺少RestModule的必需Setter
解决Dagger @Component.Builder缺少RestModule Setter的错误
这个错误的核心原因很明确:你的RestModule拥有一个带RestSettings参数的构造函数,而Dagger的@Component.Builder需要明确的方式来获取这个模块的实例——因为Dagger无法自动创建它(它不知道从哪里拿到RestSettings)。下面是两种常见的解决方案:
方案一:在Component Builder中添加RestModule的Setter方法
这是最直接的方式,手动把实例化好的RestModule传递给Dagger:
修改PresenterEnvironmentComponent的Builder
在Builder接口中添加一个专门设置RestModule的方法:
@Singleton @Component(modules = {PresenterEnvironmentModule.class, RestModule.class}) public interface PresenterEnvironmentComponent { @Component.Builder interface Builder { // 保留你现有的@BindsInstance方法 @BindsInstance Builder sharedPreferenceService(SharedPrefService sharedPreferences); @BindsInstance Builder loggingService(LoggingService loggingService); @BindsInstance Builder applicationService(Application application); @BindsInstance Builder connectivityService(ConnectivityService connectivityService); @BindsInstance Builder schedulersService(SchedulersService schedulersService); @BindsInstance Builder sessionService(SessionService sessionService); // 添加这一行:提供RestModule的setter Builder restModule(RestModule restModule); PresenterEnvironmentComponent build(); } // 保留其他方法 @NonNull PresenterEnvironment presenterEnvironment(); void inject(BaseBootstrapActivity<BaseBootstrapPresenter> baseBootstrapActivity); }
使用时传入RestModule实例
在创建Component的地方,先实例化RestModule,再通过Builder传入:
// 先准备好RestSettings实例 RestSettings restSettings = new RestSettings(...); // 实例化RestModule RestModule restModule = new RestModule(restSettings); // 创建Component PresenterEnvironmentComponent component = DaggerPresenterEnvironmentComponent.builder() .sharedPreferenceService(yourSharedPrefService) .loggingService(yourLoggingService) // 其他必要的@BindsInstance参数 .restModule(restModule) // 传入RestModule .build();
方案二:让Dagger管理RestModule的依赖(更优雅的方式)
如果你不想手动实例化RestModule,可以把RestSettings改成由Dagger注入的依赖,然后修改RestModule去掉带参构造:
修改RestModule
移除构造函数和成员变量,在需要用到RestSettings的@Provides方法中直接注入它:
@Module public class RestModule { // 去掉原来的构造函数和成员变量 @Provides @Singleton @NonNull @Type.Basic public OkHttpClient provideOkHttpClient( @NonNull RestSettings restSettings, @NonNull TokenInterceptor tokenInterceptor, @NonNull HttpLoggingInterceptor loggingInterceptor, @NonNull OkLogInterceptor okLogInterceptor, @NonNull CachingInterceptor cacheInterceptor ) { OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.addInterceptor(tokenInterceptor); // 用restSettings获取原来的成员变量值 Interceptor[] additionalInterceptors = restSettings.getAdditionalInterceptors(); if (additionalInterceptors != null && additionalInterceptors.length > 0) { for (Interceptor interceptor : additionalInterceptors) { builder.addInterceptor(interceptor); } } Function<OkHttpClient.Builder, OkHttpClient.Builder> onOkHttpClient = restSettings.getOnOkHttpClient(); if (onOkHttpClient != null) { builder = apply(onOkHttpClient, builder); } if (restSettings.isDebuggable()) { builder.addInterceptor(loggingInterceptor); builder.addNetworkInterceptor(cacheInterceptor); builder.addInterceptor(okLogInterceptor); } return builder.build(); } // 其他@Provides方法同理,把原来的成员变量替换为restSettings的调用 @Provides @Singleton @NonNull @Type.ForUploading public OkHttpClient provideOkHttpClientForUploading( @NonNull RestSettings restSettings, @NonNull TokenInterceptor tokenInterceptor, @NonNull HttpLoggingInterceptor loggingInterceptor, @NonNull OkLogInterceptor okLogInterceptor, @NonNull CachingInterceptor cacheInterceptor ) { // 同样的逻辑,用restSettings获取参数 OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.addInterceptor(tokenInterceptor); Interceptor[] additionalInterceptors = restSettings.getAdditionalInterceptors(); if (additionalInterceptors != null && additionalInterceptors.length > 0) { for (Interceptor interceptor : additionalInterceptors) { builder.addInterceptor(interceptor); } } Function<OkHttpClient.Builder, OkHttpClient.Builder> onOkHttpClientForUploading = restSettings.getOnOkHttpClientForUploading(); if (onOkHttpClientForUploading == null) { builder.writeTimeout(60, TimeUnit.SECONDS); builder.connectTimeout(60, TimeUnit.SECONDS); builder.readTimeout(60, TimeUnit.SECONDS); } else { builder = apply(onOkHttpClientForUploading, builder); } if (restSettings.isDebuggable()) { builder.addInterceptor(loggingInterceptor); builder.addNetworkInterceptor(cacheInterceptor); builder.addInterceptor(okLogInterceptor); } return builder.build(); } // 保留其他无依赖的@Provides方法 @Provides @Singleton @NonNull public OkLogInterceptor provideOkLogInterceptor() { return new OkLogInterceptor.Builder().withAllLogData().build(); } @Provides @Singleton @NonNull public HttpLoggingInterceptor provideHttpLoggingInterceptor() { HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); return interceptor; } @Provides @Singleton @NonNull @Type.Basic public Retrofit provideRetrofit(@NonNull @Type.Basic OkHttpClient client, @NonNull RestSettings restSettings) { return new Retrofit.Builder() .baseUrl(restSettings.getBaseUrl()) .client(client) .addConverterFactory(LoganSquareConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build(); } // 补全provideRetrofitForUploading方法,同样注入RestSettings }
在Component Builder中添加RestSettings的@BindsInstance方法
把RestSettings也加入到Builder的绑定中:
@Singleton @Component(modules = {PresenterEnvironmentModule.class, RestModule.class}) public interface PresenterEnvironmentComponent { @Component.Builder interface Builder { // 保留原有@BindsInstance方法 @BindsInstance Builder sharedPreferenceService(SharedPrefService sharedPreferences); @BindsInstance Builder loggingService(LoggingService loggingService); @BindsInstance Builder applicationService(Application application); @BindsInstance Builder connectivityService(ConnectivityService connectivityService); @BindsInstance Builder schedulersService(SchedulersService schedulersService); @BindsInstance Builder sessionService(SessionService sessionService); // 添加RestSettings的绑定 @BindsInstance Builder restSettings(RestSettings restSettings); PresenterEnvironmentComponent build(); } // 保留其他方法 @NonNull PresenterEnvironment presenterEnvironment(); void inject(BaseBootstrapActivity<BaseBootstrapPresenter> baseBootstrapActivity); }
使用时传入RestSettings
现在创建Component只需要传入RestSettings,Dagger会自动创建RestModule并注入所需的依赖:
RestSettings restSettings = new RestSettings(...); PresenterEnvironmentComponent component = DaggerPresenterEnvironmentComponent.builder() .sharedPreferenceService(yourSharedPrefService) .loggingService(yourLoggingService) // 其他必要参数 .restSettings(restSettings) .build();
两种方案都能解决你的问题,方案二更符合Dagger的依赖注入理念,减少手动实例化模块的代码;方案一更适合快速修复现有代码结构。
内容的提问来源于stack exchange,提问作者Hanaa Mohamed
相关产品推荐
相关产品推荐

