如何使用悬挂方法初始化ViewModel中的字段

发布于 2025-01-18 08:40:02 字数 347 浏览 3 评论 0原文

如果我需要调用悬挂函数以获取值,如何初始化视图模型中的字段?

我有悬浮函数从数据库返回值。

suspend fun fetchProduct(): Product

当我创建视图模型时,我必须在此领域中获取产品

private val selectedProduct: Product 

,我尝试这样做,但它不起作用,因为我在Coroutines之外称呼此方法

private val selectedProduct: Product = repository.fetchProduct()

How to initialize a field in view model if I need to call the suspend function to get the value?

I a have suspend function that returns value from a database.

suspend fun fetchProduct(): Product

When I create the view model I have to get product in this field

private val selectedProduct: Product 

I tried doing it this way but it doesn't work because I'm calling this method outside of the coroutines

private val selectedProduct: Product = repository.fetchProduct()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

农村范ル 2025-01-25 08:40:02

由于 fetchProduct() 是一个挂起函数,因此您必须在协程范围内调用它。

对于您的情况,我建议使用以下选项:

  1. selectedProduct 定义为可为空,并将其在 ViewModel 中初始化为 null
class AnyViewModel : ViewModel {

    private val selectedProduct: Product? = null
    

    init {
        viewModelScope.launch {
            selectedProduct = repository.fetchProduct()
        }
    }
}
  1. 将 selectedProduct 定义为 >lateinit var 并执行与上面相同的操作;

就我个人而言,我更喜欢第一个,因为我觉得我可以更好地控制变量是否已定义这一事实。

Since fetchProduct() is a suspend function, you have to invoke it inside a coroutine scope.

For you case I would suggest the following options:

  1. Define selectedProduct as nullable and initialize it inside your ViewModel as null:
class AnyViewModel : ViewModel {

    private val selectedProduct: Product? = null
    

    init {
        viewModelScope.launch {
            selectedProduct = repository.fetchProduct()
        }
    }
}
  1. Define selectedProduct as a lateinit var and do the same as above;

Personally I prefer the first cause I feel I have more control over the fact that the variable is defined or not.

初雪 2025-01-25 08:40:02

您无法按照您描述的方式初始化字段。必须从协程或另一个挂起函数调用挂起函数。要启动协程,有几个构建器:CoroutineScope.launchCoroutineScope.asyncrunBlocking。不建议在生产代码中使用后者。还有一些构建器 - liveDataflow - 可用于初始化字段。对于您的情况,我建议使用 LiveData< /a> 或 Flow 来观察字段初始化。示例代码,它使用 liveData 构建器函数调用 suspend 函数:

val selectedProduct: LiveData<Product> = liveData {
    val product = repository.fetchProduct()
    emit(product)
}

如果您想在初始化此字段后在 UI 中执行某些操作,则需要 观察它。在 ActivityFragment 中,它将如下所示:

// 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 或更高版本。

You can't initialize a field in the way you described. suspend function must be called from a coroutine or another suspend function. To launch a coroutine there are a couple of builders for that: CoroutineScope.launch, CoroutineScope.async, runBlocking. The latter is not recommended to use in production code. There are also a couple of builders - liveData, flow - which can be used to initialize the field. For your case I would recommend to use a LiveData or Flow to observe the field initialization. The sample code, which uses the liveData builder function to call a suspend function:

val selectedProduct: LiveData<Product> = liveData {
    val product = repository.fetchProduct()
    emit(product)
}

And if you want to do something in UI after this field is initialized you need to observe it. In Activity or Fragment it will look something like the following:

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

For liveData, use androidx.lifecycle:lifecycle-livedata-ktx:2.4.0 or higher.

伴我老 2025-01-25 08:40:02

您需要在协程范围内运行该函数才能获取值。

如果您在 ViewModel() 类中,您可以安全地使用 viewModelScope

private lateinit var selectedProduct:Product

fun initialize(){
    viewModelScope.launch {
        selectedProduct = repository.fetchProduct()
    }
}

You need to run the function inside a coroutine scope to get the value.

if you're in a ViewModel() class you can safely use the viewModelScope

private lateinit var selectedProduct:Product

fun initialize(){
    viewModelScope.launch {
        selectedProduct = repository.fetchProduct()
    }
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文