簡體   English   中英

ViewModel 阻止的片段返回導航

[英]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或檢查LiveDataSingleLiveEvent模式,您只能使用一次事件。

更新:

消耗品模式的可能解決方案:

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.

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