我有一个片段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。
答案 0 :(得分:0)
重写方法onBackPressed()
以处理“ <-”箭头
答案 1 :(得分:0)
好像您用来发信号通知片段A的LiveData,它应该导航到片段B实际上是一个事件。事件仅发生一次,并且一旦消耗(导航事件完成)就消失了。因此,导航后,您需要向视图模型发送一条消息,说明导航已经进行,并且相应的数据持有者应再次为(例如)null。在片段A中,检查新值是否等于null,只有在这种情况下,才发出导航事件。这样可以防止片段A在后面的情况下立即再次切换到B。
如果您想了解有关使用实时数据进行活动的更多信息,请参阅此article。