[英]Fragment Back Navigation Blocked by ViewModel
所以我試圖用導航組件實現 mvvm 架構,這個代碼片段工作得很好。問題是當我從 fragmentA 導航到 FragmentB 時,沒有辦法將 go 返回到 FragmentA,就像按鈕被阻止(如果我刪除了 ViewModel,導航工作正常,因此它與 ViewModel 有關)。
有人知道發生了什么嗎?
private fun initVewModel() {
myViewModel = MyViewModel()
myViewModel = ViewModelProviders
.of(this, createFor(myViewModel))
.get(MyViewModel::class.java)
}
private fun setupObservers() {
myViewModel.myData.observe(viewLifecycleOwner, Observer {
it?.let { resource ->
when (resource.status) {
Status.SUCCESS -> {
resource.data?.let {
val action =
FragmentADirections.actionFragmentAToFragmentB()
Navigation.findNavController(requireView()).navigate(action)
}
}
Status.ERROR -> {
//TODO show an error
loading.visibility = View.GONE
}
Status.LOADING -> {
loading.visibility = View.VISIBLE
}
}
}
})
}
這是我的視圖模型
class MyViewModel : ViewModel() {
private val searchText = MutableLiveData<String>()
//This method is called on a search button click
fun setSearchText(text: String) {
searchText.value = text
}
val myData = searchText.switchMap { text ->
liveData(Dispatchers.IO) {
emit(Resource.loading(data = null))
try {
emit(Resource.success(data = dataOrigin.getData(text)))
} catch (exception: Exception) {
exception.printStackTrace()
emit(Resource.error(data = null, message = exception.message ?: "Error Occurred!"))
}
}
}
}
那是因為您的myData
Observer
將立即使用返回導航的最新數據觸發並再次觸發SUCCESS
分支。
我建議使用SharedFlow
或檢查LiveData
的SingleLiveEvent
模式,您只能使用一次事件。
更新:
消耗品模式的可能解決方案:
class Consumable<T>(private val event: T) {
private var isConsumed = false
fun consume(): T? {
if (isConsumed) return null
isConsumed = true
return event
}
fun peek() = event
}
然后在ViewModel中:
val event = MutableLiveData<Consumable<YourEventClass>>()
...
event.value = Consumable(XYEvent)
你會像這樣觀察它:
viewModel.event.observe{ event ->
event.consume()?.let{
// Do your navigation here
}
}
此外,您可以為可消耗的 livedatas 編寫擴展 function .consume()
,它會解開值
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.