【问题标题】:Retrofit cannot be provided without an @Inject constructor or from an @Provides- or @Produces-annotated method如果没有 @Inject 构造函数或 @Provides- 或 @Produces-annotated 方法,则无法提供改造
【发布时间】:2016-06-27 15:55:31
【问题描述】:

我现在正在学习 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;
}
}

应用组件

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
    void inject(RetrofitDemo target);
}

应用模块

    private final Application mContext;

AppModule(Application context) {
    mContext = context;
}

@Singleton
@ForApplication
@Provides
Application provideApplication() {
    return mContext;
}

@Singleton
@ForApplication
@Provides
Context provideContext() {
    return mContext;
}

API组件

@Singleton
@Component(dependencies = {AppModule.class},modules =    {ApiModule.class})
public interface ApiComponent {
     void inject(RetrofitDemo target);
}

API 模块

@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,学匕首对我来说太重了……我想。


此外,在我的情况下,我在 AppComponent 中写了dependencies = AppModule.class module = ApiModule.class,我认为这似乎是对的,但是如果我写了module = ({AppComponent.class,ApiComponent.class}),它也可以正常工作。有人可以解释一下为什么吗?


请检查我的代码并给我一些建议。提前谢谢!

【问题讨论】:

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


    【解决方案1】:

    @Sinyuk 这里有很多东西要解压,Dagger 乍一看有点复杂,但我想我可以提供帮助。首先,您对@Component 注释存在概念上的误解。 Component 是您定义的接口,Dagger 通过代码生成实现该接口。您将定义接口,并使用@Component 对其进行注释,然后您将提供一组Modules 给Dagger 以在生成过程中使用。您使用的模块通过@Component 注释的modules 元素传入。如果您想让一个Component 允许另一个Component 支持注入过程,那么在注入代码时需要让Dagger 使用的任何Component 接口都将通过dependencies 元素传递@Component注解。

    --

    因此,以下不正确

    @Component(dependencies = AppModule.class  module = ApiModule.class`)
    

    相反,让一个组件使用两个模块:

    @Component(modules = {ApiModule.class, AppModule.class})
    

    或者,让一个组件使用一个模块并依赖于另一个组件

    @Component(modules = {AppModule.class}, dependencies = {ApiComponent.class})
    

    我希望这可以帮助您走上正确的道路。如果您有任何后续问题,请告诉我。

    【讨论】:

      【解决方案2】:

      好的,所以你的配置应该是这样的

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-11
        相关资源
        最近更新 更多