首页 > 解决方案 > Dagger 2 错误:依赖“不能在没有 @Provides 注释的方法的情况下提供”

问题描述

我已经开始使用带有 Android Injector 的 Dagger 2 并遇到了一个问题

我有 5 个模块,它们组成一个组件

@Singleton
@Component(modules = [AndroidInjectionModule::class,
    ActivityBuilder::class,
    AndroidSupportInjectionModule::class
    , ApplicationModule::class,NetworkModule::class])

interface ApplicationComponent {

    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(application: Application): Builder

        fun build(): ApplicationComponent
    }
    fun inject(app: DeliveryApplication)
    fun service(): DeliveryApi

}

网络模块看起来像

@Module
class NetworkModule  {

    @Singleton
    @Provides
    fun providesDeliveryApi(retrofit: Retrofit):DeliveryApi = retrofit.create(DeliveryApi::class.java)

    @Singleton
    @Provides
    fun providesRetrofit(okHttpClient: OkHttpClient):Retrofit =
            Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(okHttpClient)
                    .build()


    @Singleton
    @Provides
    fun providesOkHttpClient(context:Context): OkHttpClient {
       /* val logging = HttpLoggingInterceptor().apply {
            level = HttpLoggingInterceptor.Level.BODY
        }*/
        val cacheSize = (5 * 1024 * 1024).toLong()
        val myCache = Cache(context.cacheDir, cacheSize)

        val okHttpClient = OkHttpClient.Builder()
                .cache(myCache)
                .addInterceptor { chain ->
                    var request = chain.request()
                    request = if (hasNetwork(context)!!)
                        // setting  5 Mb Cabacity
                        request.newBuilder().header("Cache-Control", "public, max-age=" + 5).build()
                    else
                        request.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + 60 * 60 * 24 * 7).build()
                    chain.proceed(request)
                }
                .build()

        return okHttpClient
    }


    @Singleton
    @Provides
    fun provideImageLoader(context: Context) : ImageLoader {
        return PicassoImageLoader(Picasso.with(context))
    }

应用模块看起来像

const val SCHEDULER_MAIN_THREAD = "mainThread"
const val SCHEDULER_IO = "io"

@Module
class ApplicationModule {
    @Provides
    @Named(SCHEDULER_MAIN_THREAD)
    fun provideAndroidMainThreadScheduler() : Scheduler = AndroidSchedulers.mainThread()
    @Provides
    @Named(SCHEDULER_IO)
    fun provideIoScheduler() : Scheduler = Schedulers.io()

    @Provides
    @Singleton
    fun provideContext(application: Application): Context {
        return application
    }
}

ActivityBuilder 非常简单:只是将活动模块和片段模块组合在一起

@Module
abstract class ActivityBuilder {
    @PerActivity
    @ContributesAndroidInjector(modules = [FragmentsModule::class, DeliveriesModule::class])
    abstract fun bindMainActivity(): DeliveriesActivity

    @PerActivity
    @ContributesAndroidInjector(modules = [FragmentsModule::class, DeliveriesDetailsModule::class])
    abstract fun bindDeliveryDetailsActivity(): DeliveryDetailsActivity
}


@Module
 abstract class FragmentsModule {
    @ContributesAndroidInjector
    abstract fun provideDeliveriesListFragment(): DeliveriesListFragment
    @ContributesAndroidInjector
    abstract fun provideDeliveryDetailsFragment(): DeliveryDetailsFragment
}

Delivery Module,用于提供 DeliveryActivity 的所有实例

@Module
class DeliveriesModule {


    @Provides
    @PerActivity
    fun providesDeliveryRepository(deliveryApi: DeliveryApi): DeliveryRepository {
        return  DeliveryDownloader(deliveryApi)
    }


    @Provides
    @PerActivity
    fun providesDeliveryListUseCases(deliveryRepository: DeliveryRepository): DeliveryListUseCase {
        return DeliveryListInteractor(deliveryRepository)
    }



    @Provides
    @PerActivity
    fun provideDeliveriesListFragment(): DeliveriesListFragment {
        return DeliveriesListFragment()
    }

}

ViewModelFactory 哪里有问题,编译器说没有@Provides-annotated 方法就不能提供DeliveryListUseCase

class ViewModelFactory @Inject constructor(private val application: Application,
                                           @Named(SCHEDULER_IO) val subscribeOnScheduler: Scheduler,
                                           @Named(SCHEDULER_MAIN_THREAD) val observeOnScheduler: Scheduler,
        private val deliveryListUseCase: DeliveryListUseCase) : ViewModelProvider.NewInstanceFactory() {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {

        return when {
            modelClass.isAssignableFrom(DeliveryListViewModel::class.java)  ->
                DeliveryListViewModel(application,deliveryListUseCase,subscribeOnScheduler,observeOnScheduler) as T
            else -> BaseViewModel(application) as T
        }
    }
}

标签: androiddependency-injectionkotlindagger-2dagger

解决方案


好像我已经弄清楚出了什么问题

问题。DeliveriesModule 是 DeliveriesActivity 的一个模块,所以我必须为 DeliveriesListFragment 制作另一个模块并提供 DeliveryListUseCase

谢谢@Blackbelt,给我一个提示


推荐阅读