我现在正在学习Dagger 2,对于我解释没有代码的问题感到非常痛苦,所以让我首先列出我的所有模块,组件等:
App.class
public class App extends Application {
private ApiComponent mApiComponent = null;
private AppComponent mAppComponent = null;
public ApiComponent getApiComponent() {
if (mApiComponent == null) {
// Dagger%COMPONENT_NAME%
mApiComponent = DaggerApiComponent.builder()
// list of modules that are part of this component need to be created here too
.appModule(new AppModule(this)) // This also corresponds to the name of your module: %component_name%Module
.apiModule(new ApiModule(this))
.build();
}
return mApiComponent;
}
public AppComponent getAppComponent() {
if (mAppComponent == null) {
// If a Dagger 2 component does not have any constructor arguments for any of its modules,
// then we can use .create() as a shortcut instead:
mAppComponent = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();
}
return mAppComponent;
}
}
AppComponent
@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
void inject(RetrofitDemo target);
}
的AppModule
private final Application mContext;
AppModule(Application context) {
mContext = context;
}
@Singleton
@ForApplication
@Provides
Application provideApplication() {
return mContext;
}
@Singleton
@ForApplication
@Provides
Context provideContext() {
return mContext;
}
ApiComponent
@Singleton
@Component(dependencies = {AppModule.class},modules = {ApiModule.class})
public interface ApiComponent {
void inject(RetrofitDemo target);
}
APIModule
@Inject
Context application;
@Inject
public ApiModule(Context context){
this.application = context;
}
@Provides
@Singleton
Gson provideGson() {
return new GsonBuilder()
// All timestamps are returned in ISO 8601 format:
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
// Blank fields are included as null instead of being omitted.
.serializeNulls()
.create();
}
@Provides
@Singleton
OkHttpClient provideOkHttpClient() {
...
}
@Provides
@Singleton
public Retrofit provideRetrofit(Gson gson,OkHttpClient okHttpClient){
return new Retrofit.Builder()
.baseUrl(DribbleApi.END_POINT)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(okHttpClient)
.build();
}
我的活动将是这样的:
@Inject
Retrofit mRetrofit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_retrofit_demo);
((App) getApplication()).getApiComponent().inject(this);
...
以下是错误消息:
Error:(18, 10) : retrofit2.Retrofit cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method.
retrofit2.Retrofit is injected at com.sinyuk.yuk.RetrofitDemo.mRetrofit
com.sinyuk.yuk.RetrofitDemo is injected at com.sinyuk.yuk.AppComponent.inject(target)
令我困惑的是ApiModule提供的改造实例,但为什么错误按摩说它是在appComponent上注入的?我在代码中找不到任何错误的地方。 T_T,为我学习Dagger太沉重了......我想。
此外,在我的情况下,我在AppComponent中写了dependencies = AppModule.class module = ApiModule.class
,我认为这似乎是正确的,但如果我写module = ({AppComponent.class,ApiComponent.class})
,它也可以正常工作。任何人都可以解释为什么?
请审核我的代码并给我一些建议。 Thx提前!
答案 0 :(得分:4)
@Sinyuk在这里打开很多东西,Dagger乍一看有点复杂,但我想我可以提供帮助。首先,您对@Component
注释存在概念上的误解。 Component
是您定义的接口,Dagger通过代码生成实现的接口。您将定义接口,并使用@Component
对其进行注释,然后您将向Dagger提供一组Module
以用于生成过程。您使用的模块通过modules
注释的@Component
元素传入。如果您希望有一个Component
允许另一个Component
来支持注入过程,那么在注入代码时需要让Dagger使用的任何Component
接口都将通过dependencies
注释的@Component
元素。
-
因此,以下内容不正确
@Component(dependencies = AppModule.class module = ApiModule.class`)
相反,让一个Component使用两个模块写:
@Component(modules = {ApiModule.class, AppModule.class})
或者,让一个组件使用一个模块并依赖于另一个组件
@Component(modules = {AppModule.class}, dependencies = {ApiComponent.class})
我希望这能帮助你走上正确的道路。如果您有任何后续问题,请与我们联系。
答案 1 :(得分:0)
好的,所以你的配置应该是这个
public class App extends Application {
private AppComponent mAppComponent = null;
public AppComponent getAppComponent() {
if (mAppComponent == null) {
// If a Dagger 2 component does not have any constructor arguments for any of its modules,
// then we can use .create() as a shortcut instead:
mAppComponent = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();
}
return mAppComponent;
}
}
和
@Singleton
@Component(modules = {AppModule.class, ApiModule.class})
public interface AppComponent {
void inject(RetrofitDemo target);
}
和
@Module
public class AppModule {
private final Application mContext;
AppModule(Application context) {
mContext = context;
}
@Provides
Application provideApplication() {
return mContext;
}
@Provides
Context provideContext() {
return mContext;
}
}
和
@Module
public class ApiModule {
@Provides
@Singleton
Gson provideGson() {
return new GsonBuilder()
// All timestamps are returned in ISO 8601 format:
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
// Blank fields are included as null instead of being omitted.
.serializeNulls()
.create();
}
@Provides
@Singleton
OkHttpClient provideOkHttpClient() {
...
}
@Provides
@Singleton
public Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient){
return new Retrofit.Builder()
.baseUrl(DribbleApi.END_POINT)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(okHttpClient)
.build();
}
}
和
//...Activity
@Inject
Retrofit mRetrofit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_retrofit_demo);
((App) getApplication()).getAppComponent().inject(this);
...