android - 如果没有 @Inject 构造函数或来自 @Provides- 或 @Produces- 注释的方法,则不能提供改造

标签 android dependency-injection retrofit dagger dagger-2

我现在正在学习 Dagger 2,没有代码解释这个问题对我来说太痛苦了,所以让我先列出我所有的模块、组件等:


应用类

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();
}

我的 Activity 将是这样的:

    @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注入(inject)的?而且我在我的代码中找不到任何错误的地方。 T_T,学习 Dagger 对我来说太沉重了......我想。


此外,在我的例子中,我在 AppComponent 中写了 dependencies = AppModule.class module = ApiModule.class ,我认为这似乎是正确的,但是如果我写了 module = ( {AppComponent.class,ApiComponent.class}),它也工作正常。任何人都可以解释我为什么?


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

最佳答案

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

--

因此,以下是不正确的

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

相反,要让一个组件使用两个模块,请编写:

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

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

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

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

关于android - 如果没有 @Inject 构造函数或来自 @Provides- 或 @Produces- 注释的方法,则不能提供改造,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38058364/

相关文章:

android - 两个具有不同包名的 Android 应用程序使用一个 Facebook 应用程序进行共享

c# - 内置类型的依赖注入(inject)

java.lang.NullPointerException : Attempt to invoke interface method 'java.lang.Object java.util.List.get(int)'

java - 执行过程中出现Retrofit异常

android - 如何将网站包装在手机应用程序中?

android - Android 中的 Http get 请求

java - 如何将 ArrayList 计数写入 LogCat?

dependency-injection - 找不到 Angular2 http 服务

java - 如何在配置中将系统属性注入(inject)到静态bean中?

java - retrofit / Dagger - Android : Fatal Exception: API declarations must be interfaces