kotlin 如何从异步协程作用域(如ViewModelScope)返回值到用户界面?

6ie5vjzr  于 2023-05-18  发布在  Kotlin
关注(0)|答案(3)|浏览(164)

我试图从数据库中检索一个条目,并在viewModelScope的帮助下成功地将值返回到我的视图模型中,但我希望将此值返回给驻留在片段中的调用函数,以便它可以显示在TextView上。
我尝试用传统的方法返回值,但不起作用。那么,我如何从viewModelScope.launch返回这个值到调用函数?

查看模型

fun findbyID(id: Int) {
    viewModelScope.launch {
        val returnedrepo = repo.delete(id)
        Log.e(TAG, returnedrepo.toString())
        // how to return value from here to Fragment
    }
}

仓库

suspend fun findbyID(id: Int): userentity {
    val returneddao = Dao.findbyID(id)
    Log.e(TAG, returneddao.toString())
    return returneddao
}
2wnc66cl

2wnc66cl1#

LiveData可用于从ViewModelFragment获取值。
让函数findbyID返回LiveData并在片段中观察它。
ViewModel中的函数

fun findbyID(id: Int): LiveData</*your data type*/> {
    val result = MutableLiveData</*your data type*/>()
    viewModelScope.launch {
       val returnedrepo = repo.delete(id)
       result.postValue(returnedrepo)
    }
    return result.
}

Fragment中的观察者

findbyId.observer(viewLifeCycleOwner, Observer { returnedrepo ->
   /* logic to set the textview */
})
ryhaxcpt

ryhaxcpt2#

  • 感谢Nataraj KR的帮助!*
  • 以下是我的代码 *
    查看模型
class ViewModel(application: Application):AndroidViewModel(application) {
val TAG = "ViewModel"
val repo: theRepository
val alldata:LiveData<List<userentity>>
val returnedVal = MutableLiveData<userentity>()
init {
    val getDao = UserRoomDatabase.getDatabase(application).userDao()
    repo = theRepository(getDao)
    alldata = repo.allUsers

}

fun findbyID(id: Int){
    viewModelScope.launch {
       returnedVal.value = repo.findbyID(id)
    }
}

}

碎片

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)

    val usermodel = ViewModelProvider(this).get(ViewModel::class.java)
    usermodel.alldata.observe(this, Observer {
        Log.e(TAG,usermodel.alldata.value.toString())
    })
    usermodel.returnedVal.observe(this, Observer {
        tv1.text = usermodel.returnedVal.value.toString()
    })

    allData.setOnClickListener {
        tv1.text = usermodel.alldata.value.toString()
    }

    findByID.setOnClickListener {
        usermodel.findbyID(et2.text.toString().toInt())
    }
}
jckbn6z7

jckbn6z73#

另一种不使用LiveData的方法是这样的,
viewModelScope类似,也有一个lifecycleScope,它具有生命周期感知组件,可以从UI层使用。以下是示例,

碎片

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    findByID.setOnClickListener {
        lifecycleScope.launch{
            val res = usermodel.findbyID(et2.text.toString().toInt())
            // use returned value to do anything.
        }
    }
}

视图模型

//1st option
// make the function suspendable itself.use aync instead of launch and then
// use await to collect the returned value.
suspend fun findbyID(id: Int): userEntity  {
    val job = viewModelScope.async {
       val returnedrepo = repo.delete(id)
       Log.e(TAG,returnedrepo.toString())
       return@async returnedrepo
    }
    return job.await()
}

//2nd option
// make the function suspendable itself. but switch the execution on IO
// thread.(since you are making a DB call)
suspend fun findbyID(id: Int): userEntity  {
    return withContext(Dispatchers.IO){
       val returnedrepo = repo.delete(id)
       Log.e(TAG,returnedrepo.toString())
       return@withContext returnedrepo
    }
}

由于LiveData特定于Android环境,因此在某些地方使用KotlinFlow成为更好的选择,它提供了类似的功能。

相关问题