【问题标题】:Dagger 2 error: dependency “cannot be provided without an @Provides-annotated method"Dagger 2 错误:依赖“不能在没有 @Provides 注释的方法的情况下提供”
【发布时间】:2018-11-28 09:32:02
【问题描述】:

我已经开始使用带有 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 非常简单:只是活动模块的组合 和 FragmentsModule 用于片段

@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
        }
    }
}

【问题讨论】:

  • 你在哪里注入ViewModelFactory
  • 我在 DeliveriesListFragment 注入 ViewModelFactory
  • 这就是问题所在。根据您发布的DeliveryListUseCaseDeliveriesModule 提供,它是DeliveriesActivity 的一个模块

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


【解决方案1】:

我好像发现了什么问题

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

谢谢@Blackbelt 给我提示

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-06
    • 2021-05-05
    • 2021-06-11
    • 1970-01-01
    • 2019-09-04
    • 1970-01-01
    相关资源
    最近更新 更多