Android Hilt - 如何注入viewModelScope

问题描述 投票:0回答:2

我想注入 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]

以下其他入口点也依赖于它:

android kotlin dependency-injection dagger-2 kotlin-coroutines
2个回答
2
投票

我不知道你为什么要这样做,但我认为你错过了函数顶部的一些

@Provides

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

但我真的不建议这样做。如果您想要一个与视图模型一样长的协程,那么只需在视图模型内启动协程即可。


0
投票

您可以执行以下操作。

创建ViewModelModule.kt:

@Module
@InstallIn(ViewModelComponent::class)
class ViewModelModule {
    
    @Provides
    @ViewModelScoped
    fun provideViewModelScope(
        lifecycle: ViewModelLifecycle,
    ): CoroutineScope {
        val scope = CoroutineScope(Dispatchers.Main.immediate + SupervisorJob())
        lifecycle.addOnClearedListener { 
            scope.cancel()
        }
        return scope
    }
}

然后在 PostPageSource 添加

@ViewModelScoped
注释,您就可以注入您的范围:

@ViewModelScoped
class PostPageSource @Inject constructor(
    val scope: CoroutineScope,
) {
    init {
        scope.launch {
            try {
                delay(Long.MAX_VALUE)
            } catch (e: CancellationException) {
                Log.d("TAG", "Scope is cancelled, because ViewModel is destroyed")
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.