Я не могу предоставить ViewModel - PullRequest
0 голосов
/ 24 сентября 2019

Я не могу предоставить LoginViewModel, используя LoginViewModelProviderModule, когда я включаю LoginViewModelProviderModule в @ContributesAndroidInjector(modules = [MainFragmentBuilderModule::class, LoginViewModelProviderModule::class]), но он работает, когда я включаю его в аннотацию @Module в классе ActivityBuilderModule.

BaseApplicationComponent

@Suppress("unused")
@Singleton
@Component(
    modules = [AndroidInjectionModule::class,
        ActivityBuilderModule::class,
        ViewModelFactoryModule::class]
)
interface BaseApplicationComponent : AndroidInjector<BaseApplicationClass> {

    @Component.Builder
    interface Builder {

        @BindsInstance
        fun application(application: Application): Builder

        fun build(): BaseApplicationComponent
    }
}

ActivityBuilderModule

@Module
abstract class ActivityBuilderModule {

    @LoginScope
    @ContributesAndroidInjector(modules = [MainFragmentBuilderModule::class, LoginViewModelProviderModule::class])
    abstract fun contributeMainActivity(): MainActivity
}

MainFragmentBuilderModule

@Module
abstract class MainFragmentBuilderModule {

    @ContributesAndroidInjector
    abstract fun contributesLoginFragment(): LoginFragment
}

LoginViewModelProviderModule

@Suppress("unused")
@Module
abstract class LoginViewModelProviderModule {
    @Binds
    @IntoMap
    @ViewModelKey(LoginViewModel::class)
    abstract fun bindLoginViewModel(viewModel: LoginViewModel): ViewModel
}

ViewModelFactoryModule

@Module
abstract class ViewModelFactoryModule {

    @Binds
    abstract fun bindViewModelFactory(viewModelProviderFactory: ViewModelProviderFactory): ViewModelProvider.Factory
}

ViewModelProviderFactory

@Singleton
class ViewModelProviderFactory @Inject constructor(
    private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        val creator = creators[modelClass] ?: creators.entries.firstOrNull {
            modelClass.isAssignableFrom(it.key)
        }?.value ?: throw IllegalArgumentException("unknown model class $modelClass") as Throwable
        try {
            @Suppress("UNCHECKED_CAST")
            return creator.get() as T
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
    }
}

LoginScope

@Scope
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
annotation class LoginScope 

ViewModelKey

@MustBeDocumented
@Target(
    AnnotationTarget.FUNCTION,
    AnnotationTarget.PROPERTY_GETTER,
    AnnotationTarget.PROPERTY_SETTER
)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)

Я вижу эту ошибку:

Ошибка: [Dagger / MissingBinding] java.util.Map, javax.inject.Provider> не может быть предоставлен без аннотируемого метода @ Provides.открытый абстрактный интерфейс BaseApplicationComponent extends dagger.android.AndroidInjector {^ java.util.Map, javax.inject.Provider> внедряется в com.example.mydemoapplication.viewmodel_factory.ViewModelProviderFactory (создатели) com.example.mydemoappl.в com.example.mydemoapplication.LoginFragment.viewModelProviderFactory com.example.mydemoapplication.LoginFragment внедряется в dagger.android.AndroidInjector.inject (T) [com.example.mydemoapplication.dagger.BaseApplicationComponent?com.example.mydemoapplication.dagger.ActivityBuilderModule_ContributeMainActivity.MainActivitySubcomponent?com.example.mydemoapplication.dagger.MainFragmentBuilderModule_ContributesLoginFragment.LoginFragmentSubcomponent]

1 Ответ

0 голосов
/ 24 сентября 2019

Вы можете создать только модуль, связывающий все viewmodel в приложении.Вы можете увидеть подробности в моем примере приложения: sample-moviedb-app

BaseApplicationComponent:

@Suppress("unused")
@Singleton
@Component(
    modules = [AndroidInjectionModule::class,
        ActivityBuilderModule::class,
        ViewModelFactoryModule::class,
        ViewModelModule::class]

)
interface BaseApplicationComponent : AndroidInjector<BaseApplicationClass> {
    @Component.Builder
    interface Builder {

        @BindsInstance
        fun application(application: Application): Builder

        fun build(): BaseApplicationComponent
    }
}

ViewModelModule:

@Suppress("unused")
@Module
abstract class ViewModelProviderModule {
    @Binds
    @IntoMap
    @ViewModelKey(LoginViewModel::class)
    abstract fun bindLoginViewModel(viewModel: LoginViewModel): ViewModel

//other viewmodels in application
   @Binds
   abstract fun bindViewModelFactory(viewModelProviderFactory:ViewModelProviderFactory): ViewModelProvider.Factory
}

Основной модуль:

@Module
class MainModule {
    @MainActivityScope
    @Provides
    fun provideViewModel(mainActivity: MainActivity, viewModelFactory: ViewModelProviderFactory) =
        ViewModelProviders.of(mainActivity, viewModelFactory).get(LoginViewModel::class.java)
}

LoginViewModel:

class LoginViewModel @Inject constructor(
) : ViewModel() {

}
...