Android应用开发中的新功能。我正在使用kotlin,正在尝试从我的viewmodel的房间数据库中检索一个列表,并在按下按钮时对片段进行敬酒(下面的代码)。如果按一次按钮,将得到一个空字符串,但如果按两次,将得到列表。我该怎么做才能一键检索列表?可能是协程中缺少一些东西。
Viewmodel代码:
var Listado = ""
fun listaTotal(): String {
uiScope.launch {
getTodaListaCompra().forEach{
Log.i("Listado Compra",Listado )
Listado = Listado + " " + it
Log.i("Data",data.value)
Log.i("Pueba",it)
}
}
return Listado
}
片段调用:
Toast.makeText(application, tabListaCompraViewModel.listaTotal(), Toast.LENGTH_SHORT)
.show()
预先感谢
答案 0 :(得分:0)
您正在开始定义一个空字符串。首次调用listaTotal()时,将在后台启动协程以计算'listado'的值。但是,listaTotal的返回不等待后台协程完成。这就是为什么“ listado”仍然为空。
在第一次和第二次单击按钮之间,第一个协程完成,并且“ listado”现在不再为空,因此,当您第二次单击按钮时,协程再次启动,但是“ listado”再次返回在该协程完成之前,因此它将返回第一次单击按钮的结果。
因为您只能在主UI线程上进行Toast,所以需要告诉它等待协程完成以获取返回的值。您可以使用runBlocking来做到这一点,就像这样:
fun listaTotal(): String = runBlocking {
getTodaListaCompra().forEach{
Log.i("Listado Compra",listado )
listado += " " + it
Log.i("Data",data.value)
Log.i("Pueba",it)
}
listado
}
更新: 为了明确起见,此方法将阻塞主UI线程,直到返回结果。 因此,您应该考虑使用LiveData(请参阅Sergeys答案)或Flows来获取数据。该答案的目的主要是为了一般性地解释代码和协程的行为。
答案 1 :(得分:0)
我建议使用 LivaData 观察数据:
class MyViewModel : ViewModel() {
val listado: LiveData<String> = MutableLiveData<String>()
fun listaTotal() = viewModelScope.launch {
var localListado = ""
getTodaListaCompra().forEach{
localListado = "$localListado $it"
}
(listado as MutableLiveData).value = localListado
}
// function marked as suspend to suspend a coroutine without blocking the Main Thread
private suspend fun getTodaListaCompra(): List<String> {
delay(1000) // simulate request delay
return listOf("one", "two", "three")
}
}
在活动或片段中,您可以使用下一个方法实例化 ViewModel 类并观察数据:
private fun initViewModel() {
val viewModel = ViewModelProvider(
this,
viewModelFactory { MyViewModel() }
)[MyViewModel::class.java]
viewModel.listado.observe(this, androidx.lifecycle.Observer { data: String ->
Toast.makeText(application, data, Toast.LENGTH_SHORT).show()
})
viewModel.listaTotal()
}
inline fun <VM : ViewModel> viewModelFactory(crossinline f: () -> VM) = object : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(aClass: Class<T>):T = f() as T
}
另外,您可能需要导入下一个库:
api 'androidx.lifecycle:lifecycle-viewmodel-ktx:$LIFECYCLE_VERSION'