如果我需要调用暂停函数来获取值,如何在视图模型中初始化字段?
我有一个从数据库返回值的挂起函数。
suspend fun fetchProduct(): Product
当我创建视图模型时,我必须在此字段中获取产品
private val selectedProduct: Product
我尝试这样做,但它不起作用,因为我在协程之外调用此方法
private val selectedProduct: Product = repository.fetchProduct()
您无法按照描述的方式初始化字段。suspend
函数必须从协程或其他suspend
函数调用。要启动协程,有几个构建器:CoroutineScope.launch
、CoroutineScope.async
、runBlocking
。不建议在生产代码中使用后者。还有一些构建器 -liveData
、flow
- 可用于初始化字段。对于您的情况,我建议使用LiveData
或Flow
来观察字段初始化。使用liveData
生成器函数调用suspend
函数的示例代码:
val selectedProduct: LiveData<Product> = liveData {
val product = repository.fetchProduct()
emit(product)
}
如果你想在初始化这个字段后在UI中做一些事情,你需要观察它。在Activity
或Fragment
中,它将如下所示:
// Create the observer which updates the UI.
val productObserver = Observer<Product> { product ->
// Update the UI, in this case, a TextView.
productNameTextView.text = product.name
}
// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
viewModel.selectedProduct.observe(this, productObserver)
对于liveData
,请使用androidx.lifecycle:lifecycle-livedata-ktx:2.4.0
或更高版本。
由于fetchProduct()
是一个挂起函数,因此必须在协程作用域内调用它。
对于您的情况,我会建议以下选项:
- 将
selectedProduct
定义为可为空,并在ViewModel
中将其初始化为null
:
class AnyViewModel : ViewModel {
private val selectedProduct: Product? = null
init {
viewModelScope.launch {
selectedProduct = repository.fetchProduct()
}
}
}
- 将选定产品定义为
lateinit var
并执行与上述相同的操作;
就个人而言,我更喜欢第一个原因,因为我觉得我可以更好地控制变量是否定义的事实。
您需要在协程范围内运行函数才能获取值。
如果你在ViewModel()类中,你可以安全地使用viewModelScope。
private lateinit var selectedProduct:Product
fun initialize(){
viewModelScope.launch {
selectedProduct = repository.fetchProduct()
}
}