【问题标题】:Dagger 2 cannot be provided without an @Provides-annotated method没有@Provides-annotated 方法就不能提供 Dagger 2
【发布时间】:2017-01-08 14:27:04
【问题描述】:

我知道有很多类似的问题,但我仍然无法为我的问题找到解决方案,在这个阶段,我没有想法。我有以下设置:

  • 应用程序模块/组件:仅用于上下文和应用程序对象。
  • Net 模块/组件:改造客户端
  • City 模块/组件:在 MVP 屏幕中注入依赖项的模块/组件。我想在 Fragment 中注入 Presenter 和 Interactor。
  • PlaceRequests:改造界面

这就是代码的样子:

ApplicationModule.java

@Module
public class ApplicationModule {
    private Application mApp;

    public ApplicationModule(Application app) {
        mApp = app;
    }

    @Provides
    @Singleton
    public Application provideApplication() {
        return mApp;
    }

    @Provides
    @Singleton
    Context provideApplicationContext() {
        return mApp.getApplicationContext();
    }
}

ApplicationComponent.java

@Singleton
@Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {
    Application application();
    Context getContext();
}

NetModule.java

@Module
public class NetModule {

    String mBaseUrl;

    public NetModule(String baseUrl) {
        this.mBaseUrl = baseUrl;
    }

    @Provides
    @Singleton
    SharedPreferences providesSharedPreferences(Application application) {
        return PreferenceManager.getDefaultSharedPreferences(application);
    }

    @Provides
    @Singleton
    Cache provideOkHttpCache(Application application) {
        int cacheSize = 10 * 1024 * 1024; // 10 MiB
        return new Cache(application.getCacheDir(), cacheSize);
    }

    @Provides
    @Singleton
    OkHttpClient provideOkHttpClient(Cache cache) {
        OkHttpClient client = new OkHttpClient();
        client.setCache(cache);
        return client;
    }

    @Provides
    @Singleton
    Retrofit provideRetrofit(OkHttpClient okHttpClient) {
        return new Retrofit.Builder()
                .addConverterFactory(JacksonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .baseUrl(mBaseUrl)
                .client(okHttpClient)
                .build();
    }

    @Provides
    @Singleton
    PlaceRequests providePlaceRequests(Retrofit retrofit) {
        return retrofit.create(PlaceRequests.class);
    }
}

NetComponent.java

@Singleton
@Component(
        dependencies = {ApplicationModule.class},
        modules = {NetModule.class}
)
public interface NetComponent {
    Application application();
    PlaceRequests getPlaceRequests();
}

CityModule.java

@Module
public class CityModule {

    private CityMvp.View view;

    public CityModule(CityMvp.View view) {
        this.view = view;
    }

    @Provides
    public CityMvp.View provideView() {
        return view;
    }

    @Provides
    public CityMvp.Interactor provideInteractor(PlaceRequests placeRequests) {
        return new CityInteractor(placeRequests);
    }

    @Provides
    public CityPresenter providePresenter(CityMvp.View cityView, CityMvp.Interactor interactor) {
        return new CityPresenter(cityView, interactor);
    }
}

CityComponent.java

@PerFragment
@Component(
        dependencies = {NetModule.class},
        modules = {CityModule.class}
)

public interface CityComponent {
    void inject(CityFragment cityFragment);
}

CityInteractor.java(无法注入导致 PlaceRequests 依赖的那个)

public class CityInteractor implements CityMvp.Interactor {

    private PlaceRequests placeRequests;

    public CityInteractor(PlaceRequests placeRequests) {
        this.placeRequests = placeRequests;
    }

    @Override
    public void getPlaceDetails(String placeId, String key, Subscriber<PlaceDetails> subscriber) {
        Observable<PlaceDetails> observable = placeRequests.getPlaceDetails(placeId, key);
        observable.observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(subscriber);
    }
}

最后是错误跟踪:

    : error: com.blabla.blabla.webapi.place.PlaceRequests cannot be provided without an @Provides-annotated method.
    void inject(CityFragment cityFragment);
         ^
      com.blabla.blabla.screens.city.CityFragment.presenter
          [injected field of type: com.blabla.blabla.screens.city.CityPresenter presenter]
      com.blabla.blabla.di.modules.CityModule.providePresenter(com.blabla.blabla.screens.city.CityMvp.View cityView, com.blabla.blabla.screens.city.CityMvp.Interactor interactor)
          [parameter: com.blabla.blabla.screens.city.CityMvp.Interactor interactor]
      com.blabla.blabla.di.modules.CityModule.provideInteractor(com.blabla.blabla.webapi.place.PlaceRequests placeRequests)
          [parameter: com.blabla.blabla.webapi.place.PlaceRequests placeRequests]
3 errors
:app:compileDebugJavaWithJavac FAILED

FAILURE: Build failed with an exception.

据我了解,我在 NetComponent.java 中公开 PlaceRequests 对象,而 NetModule.java 是 CityComponent 的依赖项。为什么我无法从 CityComponent 获取 PlaceRequests 依赖项?我错过了什么?谢谢!

【问题讨论】:

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


    【解决方案1】:

    通过@Component(dependencies={...}) 指定的Component dependencies 不应该是模块,因为你有它们。它们应该是通过称为 provision 方法 的零参数方法使依赖项可用的类型(通常是组件)。

    将您的依赖项切换到组件而不是模块。

    如果有帮助,您可能想改变您对组件、模块和组件依赖项的看法。您可以将 Dagger 视为创建对象图,其中 模块定义图的输入或绑定组件定义图的输出或消费者。这使得组件依赖项成为类型或组件,包括或从另一个外部源导入,可能包括不同的 Dagger 创建的组件,但可能不包括模块——而不是依赖于您将依赖于使用该模块的组件的模块。

    【讨论】:

    • 你就是男人!谢谢,现在可以了! :) NetComponent 如何将 ApplicationModule 作为依赖项工作?
    • @Rafag 因为它们恰好是零参数方法。但是,您不能指望所有@Provides 方法。它现在起作用只是一个幸运的意外。
    猜你喜欢
    • 2018-07-09
    • 1970-01-01
    • 1970-01-01
    • 2021-06-30
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多