[英]How to return value from async coroutine scope such as ViewModelScope to your UI?
I'm trying to retrieve a single entry from the Database and successfully getting the value back in my View Model with the help of viewModelScope, but I want this value to be returned back to the calling function which resides in the fragment so it can be displayed on a TextView.我正在尝试从数据库中检索单个条目,并在 viewModelScope 的帮助下成功地将值返回到我的视图 Model 中,但我希望将此值返回给驻留在片段中的调用 function显示在 TextView 上。 I tried to return the value the conventional way but it didn't work.
我试图以传统方式返回值,但它不起作用。 So, How Can I return this value from viewModelScope.launch to the calling function?
那么,如何将 viewModelScope.launch 中的这个值返回给调用 function?
View Model查看 Model
fun findbyID(id: Int) {
viewModelScope.launch {
val returnedrepo = repo.delete(id)
Log.e(TAG,returnedrepo.toString())
// how to return value from here to Fragment
}
}
Repository存储库
suspend fun findbyID(id : Int):userentity{
val returneddao = Dao.findbyID(id)
Log.e(TAG,returneddao.toString())
return returneddao
}
LiveData
can be used to get value from ViewModel
to Fragment
. LiveData
可用于从ViewModel
获取值到Fragment
。
Make the function findbyID
return LiveData
and observe it in the fragment.使函数
findbyID
返回LiveData
并在片段中观察它。
Function in ViewModel
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.
}
Observer in Fragment
Fragment
观察者
findbyId.observer(viewLifeCycleOwner, Observer { returnedrepo ->
/* logic to set the textview */
})
Thank you Nataraj KR for your Help!感谢 Nataraj KR 的帮助!
Following is the code that worked for me.以下是对我有用的代码。
View Model查看模型
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)
}
}
} }
Fragment分段
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())
}
}
Another way without using LiveData would be like this,另一种不使用 LiveData 的方法是这样的,
Similar to viewModelScope
there is also a lifecycleScope
available with lifecycle-aware components, which can be used from the UI layer.与
viewModelScope
类似,还有一个可以用于lifecycleScope
周期感知组件的生命周期范围,可以从 UI 层使用。 Following is the example,以下是示例,
Fragment分段
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.
}
}
}
ViewModel视图模型
//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
}
}
Since LiveData is specific to Android Environment, Using Kotlin Flow becomes a better option in some places, which offers similar functionality.由于 LiveData 特定于 Android 环境,因此在某些地方使用 Kotlin Flow 成为更好的选择,它提供了类似的功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.