繁体   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