Ошибка Dagger 2: зависимость «не может быть предоставлена ​​без аннотируемого метода @ Provides» - PullRequest
0 голосов
/ 28 ноября 2018

Я начал использовать Dagger 2 с Android Injector и столкнулся с проблемой

У меня есть 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 довольно прост: просто комбинация модулей для Activity и 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
}

Модуль доставки, который использовался для обеспечения всехэкземпляры 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, где проблема здесь, компилятор говорит, что DeliveryListUseCase не может быть предоставлен без аннотируемого метода @ Provides

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

1 Ответ

0 голосов
/ 28 ноября 2018

Похоже, я понял, в чем проблема

проблема.DeliveriesModule, который является модулем DeliveriesActivity, поэтому мне нужно сделать еще один модуль для DeliveriesListFragment и предоставить DeliveryListUseCase

Спасибо, @Blackbelt, за подсказку

...