无法提供匕首改装
Posted
技术标签:
【中文标题】无法提供匕首改装【英文标题】:Dagger retrofit cannot be provided 【发布时间】:2018-08-18 21:27:21 【问题描述】:诚然,Dagger 很难,我正在尝试注入 Retrofit。我注入了 Context 和 SharedPreferences,它运行良好。但 Retrofit 打破了这一切。 它识别 DaggerRetrofitComponent 类,但没有找到 DaggerAppComponent。
改造模块:
@Module
public class RetrofitModule
public static final String BASE_URL = "http://api.themoviedb.org/3/";
@Provides
HttpLoggingInterceptor getHttpLoggingInterceptor()
return new HttpLoggingInterceptor();
@Provides
OkHttpClient getOkHttpClient(HttpLoggingInterceptor interceptor)
return new OkHttpClient.Builder().addInterceptor(interceptor).build();
@Provides
GsonConverterFactory getGsonConverterFactory()
return GsonConverterFactory.create();
@Provides
Retrofit getRetrofit(GsonConverterFactory gsonConverterFactory, OkHttpClient client)
return new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(gsonConverterFactory)
.client(client).build();
应用:
public class MyApplication extends Application
private static AppComponent appComponent;
public static AppComponent getAppComponent()
return appComponent;
@Override
public void onCreate()
super.onCreate();
appComponent=buildComponent();
protected AppComponent buildComponent()
if(BuildConfig.DEBUG)
Timber.plant(new Timber.DebugTree());
return DaggerAppComponent.builder().sharedPreferenceModule(new SharedPreferenceModule()).contextModule(new ContextModule(this)).build();
应用组件:
@Singleton
@Component(modules = ContextModule.class, SharedPreferenceModule.class)
public interface AppComponent
void inject(MainActivity mainActivity);
改造组件:
@Singleton
@Component(modules = RetrofitModule.class)
public interface RetrofitComponent
void injectRetrofit(Activity activity);
//
主活动:
public class MainActivity extends AppCompatActivity
@Inject
Context context;
@Inject
SharedPreferences sharedPreferences;
@Inject
Retrofit retrofit;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerRetrofitComponent.builder().retrofitModule(new RetrofitModule()).build().injectRetrofit(this);
MyApplication.getAppComponent().inject(this);
【问题讨论】:
【参考方案1】:删除这个类:
//@Singleton
//@Component(modules = RetrofitModule.class)
//public interface RetrofitComponent
// void injectRetrofit(Activity activity);
//
//
并修改AppComponent
:
@Singleton
@Component(modules = ContextModule.class, SharedPreferenceModule.class, RetrofitModule.class)
public interface AppComponent
void inject(MainActivity mainActivity);
【讨论】:
这可行,但我如何分离应用程序和活动级别的依赖关系 Retrofit 不是 Activity 级别的依赖,它被标记为@Singleton
。
是的,我明白了。但是你能举一个关于活动级别依赖的例子吗(不一定要改造)。
@Bissisingh 您的活动演示者是活动范围依赖的示例。
@mt0s 但是我是否注入了演示者,例如,除了我可以将所有内容转储到应用程序级别这似乎不太好。【参考方案2】:
我不确定你为什么要让 Retrofit 成为一个组件(你的应用组件中的一个模块应该足够了),那么你应该使用最后一个 Dagger 版本来处理控制器视图(活动和片段)的自动注入
@Singleton
@Component(modules = [ApplicationModule::class])
interface ApplicationComponent : androidInjector<MyApplication>
override fun inject(application: MyApplication)
@Component.Builder
interface Builder
@BindsInstance
fun application(application: MyApplication): Builder
fun build(): ApplicationComponent
__
@Module(includes = [AndroidSupportInjectionModule::class,ActivityBuilderModule::class, NetworkModule::class])
abstract class ApplicationModule
@Binds
@Singleton
abstract fun bindApplication(application: MyApplication): Application
@Module
companion object
@Provides
@Singleton
@ApplicationContext
@JvmStatic
fun provideApplicationContext(application: MyApplication): Context = application
__
@Module
abstract class ActivityBuilderModule
@ContributesAndroidInjector(modules = [MainActivityModule::class])
@ActivityScope
abstract fun contributeMainActivity(): MainActivity
//others activities there
@Module
object NetworkModule
// For simplicity just retrofit provider, but all others network resources should be here of course
@Provides
@Singleton
@JvmStatic
fun provideRetrofit(rxJava2CallAdapterFactory: RxJava2CallAdapterFactory,
nullOrEmptyConverterFactory: Converter.Factory,
@ApplicationContext okHttpClient: OkHttpClient,
gsonConverterFactory: GsonConverterFactory): Retrofit =
Retrofit.Builder()
.addCallAdapterFactory(rxJava2CallAdapterFactory)
.addConverterFactory(nullOrEmptyConverterFactory)
.addConverterFactory(gsonConverterFactory)
.baseUrl(BASE_URL)
.client(okHttpClient)
.build()
__
class MyApplication : DaggerApplication()
private val applicationInjector = DaggerApplicationComponent.builder()
.application(this)
.build()
public override fun applicationInjector() = applicationInjector
__
然后从您的活动/片段中使它们从 DaggerActivity 或 DaggerFragment 继承,您应该能够开箱即用地进行注入
你可以看看我的模板项目https://github.com/SamYStudiO/beaver它可能会有所帮助。
ps : 抱歉都是 kotlin 但应该很容易转换为 java
【讨论】:
Kotlin 不是问题,但我还没有研究过大多数像 JVMstatic 这样的注释。 什么是ActivityBuilderModule? 我添加了它(从应用程序组件创建活动子组件很有用),如果你错过了所有来自它的东西,请查看我的 github 链接 @JvmStatic 只是一个注解,告诉 java 它是一个静态方法,因为 kotlin 没有静态关键字 MainActivityModule?我似乎无法在 github repo 上找到它【参考方案3】:Dagger 2 不允许从多个组件注入依赖项。您应该考虑使用子组件。
https://google.github.io/dagger/subcomponents.html
UPD:我建议您创建从您的 AppComponent 派生的子组件,例如 NetComponent。然后在您的活动中提供 getNetComponent.inject() 。由于 NetComponent 将从 AppComponent 派生,因此它将提供您需要的 appComponent 的所有依赖项
它有点复杂,但它是正确的方法,你也应该了解 Dagger Scopes。
或
将网络依赖项放入 AppComponent 的快速方法。
【讨论】:
以上是关于无法提供匕首改装的主要内容,如果未能解决你的问题,请参考以下文章
匕首刀柄:注释类@Singleton 和提供函数@Singleton 之间的区别