Android Hilt — как внедрить viewModelScope

#android #kotlin #dependency-injection #dagger-2 #kotlin-coroutines

#Android #kotlin #внедрение зависимостей #кинжал-2 #kotlin-сопрограммы

Вопрос:

Я хочу внедрить viewModelscope, но я просто не мог этого сделать.

 class PostPageSource @Inject constructor(
val repository: MyRepository,
val scope: CoroutineScope,
val mapper: MyMapper
) : PageKeyedDataSource<Int, Posts>() {
  

Вывод ошибки выглядит следующим образом:

 [Dagger/MissingBinding] kotlinx.coroutines.CoroutineScope cannot be provided without an @Provides-annotated method.
public abstract static class ApplicationC implements App_GeneratedInjector,
  

Я пытался:

 @Module
@InstallIn(FragmentComponent::class)
object PagingModule {

@Singleton
@Provides
fun provideViewModel(fragment: Fragment) : UserDetailViewModel {
    val viewModel: UserDetailViewModel by (fragment as UserDetailFragment).viewModels()
    return viewModel
}

fun provideCorountineScope(fragment: UserDetailViewModel): CoroutineScope {
    return fragment.viewModelScope
}

}
  

Вывод ошибки выглядит следующим образом:

 error: [Dagger/MissingBinding] kotlinx.coroutines.CoroutineScope cannot be provided without an @Provides-annotated method.
public abstract static class ApplicationC implements App_GeneratedInjector,
                     ^
  kotlinx.coroutines.CoroutineScope is injected at
      com.maksu.insider.userdetail.paging.PostPageSource(…, scope, …)
  javax.inject.Provider<com.maksu.insider.userdetail.paging.PostPageSource> is injected at
      com.maksu.insider.userdetail.paging.PostPageSourceFactory(providerDataSource)
  javax.inject.Provider<com.maksu.insider.userdetail.paging.PostPageSourceFactory> is injected at
      com.maksu.insider.userdetail.UserDetailViewModel_AssistedFactory(…, dataSourceFactory)
  com.maksu.insider.userdetail.UserDetailViewModel_AssistedFactory is injected at
      com.maksu.insider.userdetail.UserDetailViewModel_HiltModule.bind(factory)
  java.util.Map<java.lang.String,javax.inject.Provider<androidx.hilt.lifecycle.ViewModelAssistedFactory<? extends androidx.lifecycle.ViewModel>>> is injected at
      androidx.hilt.lifecycle.ViewModelFactoryModules.ActivityModule.provideFactory(…, viewModelFactories)
  @dagger.hilt.android.internal.lifecycle.DefaultActivityViewModelFactory java.util.Set<androidx.lifecycle.ViewModelProvider.Factory> is requested at
      dagger.hilt.android.internal.lifecycle.DefaultViewModelFactories.ActivityEntryPoint.getActivityViewModelFactory() [com.maksu.insider.App_HiltComponents.ApplicationC → com.maksu.insider.App_HiltComponents.ActivityRetainedC → com.maksu.insider.App_HiltComponents.ActivityC]
  

От этого также зависят следующие другие точки входа:

Ответ №1:

Я не знаю, почему вы хотите это сделать, но я думаю, что вы упускаете что-то @Provides в верхней части своей функции:

 @Provides
fun provideCorountineScope(fragment: UserDetailViewModel): CoroutineScope {
    return fragment.viewModelScope
}
  

Но я действительно не рекомендую это делать. Если вам нужна сопрограмма, которая должна длиться столько же, сколько и viewmodel, просто запустите сопрограмму внутри viewmodel.

Комментарии:

1. Одна из причин, по которой вы хотите это сделать, — использовать внедренный CoroutineScope при преобразовании потока в поток состояний, например, shareIn(externalScope, 1, SharingStarted. WhileSubscribed()) — он должен жить дольше, чем observer во фрагменте, поэтому ViewModel может подойти, если вы не хотите предоставлять applicationScope . Другой случай — при использовании запуска, например, externalScope.launch{…}.join()