簡體   English   中英

從片段單擊“返回”時,觀察者出現應用程序崩潰/導航問題

[英]Application Crash/Navigation issue with observer when clicking “back” from fragment

我有一個片段A,該片段將搜索查詢發送到網絡,如果結果是肯定的,則使用Android導航組件導航到片段B,並使用觀察者完成操作。

導航到片段B后,我單擊屏幕頂部的“ <-”箭頭,但沒有導航回到片段A,而是再次重新加載了片段B。 並且,如果使用設備上的本機“后退”按鈕,則應用程序將崩潰,並顯示“ illegalArgumentException導航目標未知”錯誤。

我檢查了互聯網上有關此問題的線索,但是我所知道的是,發生這種情況是因為我在onViewCreated()中使用.observe,當我返回時,它又被調用了,並且因為livedata已經包含了某些東西,所以導航我回到B。

我嘗試在onActivityCreated()中進行觀察,並使用getViewLifeCycleOwner,但沒有成功……唯一有用的方法是在使用.observe之前檢查livedata是否具有觀察者並返回true,但是似乎不正確。

這是viewModel:

private val getAssetResult = MutableLiveData<GeneralResponse<Asset>>()
private val updateAssetResult = MutableLiveData<GeneralResponse<Int>>()
private val deleteAssetResult = MutableLiveData<GeneralResponse<Int>>()

init {
    state.value = ViewState(false)
    Log.d(TAG, "State in init: $state")
}

fun getAssetResult(): LiveData<GeneralResponse<Asset>>{

    return getAssetResult
}

fun findAsset(req: GetAssetRequest) {

    scope.launch {
        setProgressIndicator(true)
        val result = repository.getAsset(req)

        getAssetResult.postValue(result)

        setProgressIndicator(false)
    }
}

這是片段:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    viewModel = ViewModelProvider(this).get(EditAssetViewModel::class.java)
    setupViewModel()
    initFields()
}


private fun setupViewModel() {

    if (viewModel.getAssetResult().hasObservers()) // <- This is the part that prevents the app from crashing.
        return

    viewModel.getAssetResult().observe(this, Observer {
        if (it == null) return@Observer

        handleSearchResult(it)
    })

    if (viewModel.getState().hasObservers())
        return

    viewModel.getState().observe(this, Observer { handleState(it) })
}

private fun handleSearchResult(response: GeneralResponse<Asset>) {

    if (response.singleValue == null) {
        Toast.makeText(context!!, response.errorMessage, Toast.LENGTH_SHORT).show()
        return
    }

    targetFragment?.let { it ->

        val bundle = bundleOf("asset" to response.singleValue)

        when(it) {
            "UpdateLocation" ->
                Navigation.findNavController(view!!).navigate(R.id.updateLocation, bundle)
            "EditAsset" -> {
                Navigation.findNavController(view!!).navigate(R.id.editAsset, bundle)
            }
        }
    }
}

如果我從setupViewModel函數中刪除此部分:

如果(viewModel.getAssetResult()。hasObservers())返回

使用設備按鈕單擊“后退”時,該應用程序將崩潰,或者返回到片段A,僅由於.observe功能而被導航回到片段B。

重寫onBackPressed()方法以處理“ <-”箭頭

似乎您用來發信號通知片段A的LiveData應該導航到片段B實際上是一個事件。 事件僅發生一次,並且一旦消耗(導航事件完成)就消失了。 因此,在導航之后,您需要向視圖模型發送一條消息,該消息已發生導航,並且相應的數據持有者應再次(例如)為null。 在片段A中,檢查新值是否等於null,只有在這種情況下,才發出導航事件。 這樣可以防止片段A在后面的情況下立即再次切換到B。

如果您想了解更多有關使用實時數據進行事件的方法,請參閱本文

暫無
暫無

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

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