2

Code

I just started learning dagger2 and facing issue in implementation of following modules.

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

App:

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

AppModule:

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

Error

I'm getting error from this implementation is...

error: [Dagger/MissingBinding] com.example.package.data.DataManager cannot be provided without an @Provides-annotated method.

 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]
M. Twarog
  • 2,418
  • 3
  • 21
  • 39
Parveen Sharma
  • 103
  • 1
  • 10

1 Answers1

2

Dagger can't inject interfaces. Nor you can.

I see that DataManager is an interface. If you want to inject it's implementation you need to use this code if we assume that the implementation is called: DataManagerImpl.

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

Otherwise your code just does not make sense. I mean here:

@Singleton
 class ViewModelProviderFactory @Inject
 constructor(
 private val dataManager: DataManager, <<<<------ HERE?!
 private val schedulerProvider: SchedulerProvider
 ) : ViewModelProvider.NewInstanceFactory() {
Yavor Mitev
  • 1,363
  • 1
  • 10
  • 22