Как исправить ошибку «невозможно обеспечить без аннотированного метода @ Provides» в библиотеке dagger2 - PullRequest
0 голосов
/ 24 октября 2019

Код

Я только начал изучать dagger2 и столкнулся с проблемой при реализации следующих модулей.

AppComponent:

@Singleton
@Component(modules = [AndroidInjectionModule::class, AppModule::class, ActivityBuilder::class])
interface AppComponent {

fun inject(app: App)

@Component.Builder
interface Builder {

    @BindsInstance
    fun application(application: Application): Builder

    fun build(): AppComponent
}
}

Приложение:

class App : Application(), HasAndroidInjector {

  @Inject
  lateinit var androidInjector: DispatchingAndroidInjector<Any>

  override fun androidInjector() = androidInjector

  override fun onCreate() {
    super.onCreate()
    initDagger()
  }

  private fun initDagger() {
    DaggerAppComponent.builder()
        .application(this)
        .build()
        .inject(this)
  }
}

Модуль приложения:

@Module
class AppModule {

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

  @Provides
  @ApiInfo
  fun provideApiKey(): String {
    return "mApiKey"
  }

  @Provides
  @Singleton
  fun providePreferencesHelper(appPreferencesHelper: AppPreferencesHelper): PreferencesHelper {
    return appPreferencesHelper
  }

  @Provides
  fun provideSchedulerProvider(): SchedulerProvider {
    return AppSchedulerProvider()
  }
 }

DataManager

interface DataManager : PreferencesHelper {

    enum class LoggedInMode constructor(type: Int) {

    LOGGED_IN_MODE_LOGGED_OUT(0),
    LOGGED_IN_MODE_GOOGLE(1),
    LOGGED_IN_MODE_FB(2),
    LOGGED_IN_MODE_SERVER(3);

    private var mType: Int = type

    fun getType(): Int {
        return mType
    }
   }
 }

ActivityBuilder:

@Module
abstract class ActivityBuilder {

  @ContributesAndroidInjector
  abstract fun bindSplashActivity(): SplashActivity 
}

ViewModelProviderFactory:

 @Singleton
 class ViewModelProviderFactory @Inject
 constructor(
 private val dataManager: DataManager,
 private val schedulerProvider: SchedulerProvider
 ) : ViewModelProvider.NewInstanceFactory() {

     override fun <T : ViewModel> create(modelClass: Class<T>): T {
    if (modelClass.isAssignableFrom(SplashViewModel::class.java)) {
        return SplashViewModel(dataManager, schedulerProvider) as T
    }
    throw IllegalArgumentException("Unknown ViewModel class: " + modelClass.name)
   }
 }

Ошибка

Я получаю ошибку от этой реализации ...

Ошибка: [Dagger / MissingBinding] com.example.package.data.DataManager не может быть предоставлен без аннотируемого метода @ Provides.

 public abstract interface AppComponent {
            ^
  com.example.package.data.DataManager is injected at
      com.example.package.ViewModelProviderFactory(dataManager, …)
  com.example.package.ViewModelProviderFactory is injected at
      com.example.package.ui.splash.SplashActivity.factory
  com.example.package.ui.splash.SplashActivity is injected at
      dagger.android.AndroidInjector.inject(T) [com.example.package.di.component.AppComponent ? com.example.package.di.builder.ActivityBuilder_BindSplashActivity.SplashActivitySubcomponent]

1 Ответ

0 голосов
/ 25 октября 2019

Кинжал не может вводить интерфейсы. Ни вы не можете.

Я вижу, что DataManager - это интерфейс. Если вы хотите внедрить его реализацию, вам нужно использовать этот код, если мы предполагаем, что реализация называется: DataManagerImpl.

      @Provides
      fun provideDataManager (): DataManager {
        return DataManagerImpl()
      }

В противном случае ваш код просто не имеет смысла. Я имею в виду здесь:

@Singleton
 class ViewModelProviderFactory @Inject
 constructor(
 private val dataManager: DataManager, <<<<------ HERE?!
 private val schedulerProvider: SchedulerProvider
 ) : ViewModelProvider.NewInstanceFactory() {
...