簡體   English   中英

如何將 ViewModelScope 等異步協程 scope 的值返回到您的 UI?

[英]How to return value from async coroutine scope such as ViewModelScope to your UI?

我正在嘗試從數據庫中檢索單個條目,並在 viewModelScope 的幫助下成功地將值返回到我的視圖 Model 中,但我希望將此值返回給駐留在片段中的調用 function顯示在 TextView 上。 我試圖以傳統方式返回值,但它不起作用。 那么,如何將 viewModelScope.launch 中的這個值返回給調用 function?

查看 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
    }

}

存儲庫

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

LiveData可用於從ViewModel獲取值到Fragment

使函數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 */
})

感謝 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())
    }
}

另一種不使用 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 環境,因此在某些地方使用 Kotlin Flow 成為更好的選擇,它提供了類似的功能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM