没有@Inject构造函数或@ Provide-或@ Produces-annotated方法,不能提供改造

时间:2016-06-27 15:55:31

标签: android dependency-injection retrofit dagger dagger-2

我现在正在学习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提前!

2 个答案:

答案 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);
...