Kotlin协程列表返回空值

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

预先感谢

wmh071230 回答:Kotlin协程列表返回空值

您正在开始定义一个空字符串。首次调用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来获取数据。该答案的目的主要是为了一般性地解释代码和协程的行为。

,

我建议使用 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'
本文链接:https://www.f2er.com/3087208.html

大家都在问