[英]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.