当我在 LiveData 观察者中使用 navController 时,Android Navigation 组件图停止正常工作
Posted
技术标签:
【中文标题】当我在 LiveData 观察者中使用 navController 时,Android Navigation 组件图停止正常工作【英文标题】:Android Navigation component graph stop working properly when I use navController in LiveData observer 【发布时间】:2019-05-03 16:43:49 【问题描述】:我在我的演示应用程序中使用了 android 导航组件。我有一个非常简单的案例。一个活动,两个片段,A 和 B。我已经设置了导航控件,就像 Google 的示例应用程序一样。当我尝试使用简单的 onClickListener 从 A 打开片段 B 时,如下所示:
val button.setOnClickListener
val action = AFragmentDirections.openFragmentB()
findNavController().navigate(action)
一切正常。 B 片段打开,并通过点击后退按钮弹出。 但是当我尝试从 LiveData 观察者中使用它时,就像这样:
viewModel.openFragmentB.observe(viewLifecycleOwner, Observer
val action = AFragmentDirections.openFragmentB()
findNavController().navigate(action)
)
片段 B 打开,但通过点击后退按钮应用程序崩溃并出现错误 导航目的地 com.myapp:id/open_fragmetn_b 对此 NavController 是未知的。
为什么会发生这种情况以及如何将导航组件与 LiveData 一起使用?
【问题讨论】:
【参考方案1】:发生此崩溃是因为当您单击后退按钮时,您的 viewmodel openFragmentB 观察者会再次收到通知,并且它正在尝试使用操作 openFragmentB 导航到 Fragment B,但此时 NavController 当前目标仍然是 Fragment B,并且 Fragment B没有动作 openFragmentB。
对此有多种解决方案,最简单的一种是在观察者内部添加检查值是否不为空,最后将 openFragmentB 值设置为空:
if(it!=null)
val action = AFragmentDirections.openFragmentB()
findNavController().navigate(action)
viewModel.openFragmentB.value=null
但为了获得更好的方法,您可以阅读有关 SingleLIveEvent 的信息: https://medium.com/androiddevelopers/livedata-with-snackbar-navigation-and-other-events-the-singleliveevent-case-ac2622673150
【讨论】:
我已经在使用 LiveEvent,但由于某种原因,我使用 livedata 进行导航,但有一天我被卡住了。你的帖子和这篇文章对我帮助很大。谢谢! 啊...我终于明白为什么子片段的navigateUp
在循环...使用单事件方法解决了它。【参考方案2】:
感谢@Alex 的回答,我创建了您提到的相同类,并且只添加了初始可选构造函数,如下所示:
import android.util.Log
import androidx.annotation.MainThread
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import java.util.concurrent.atomic.AtomicBoolean
class SingleLiveEvent<T>(initialVal: T? = null) : MutableLiveData<T?>()
init
if(initialVal != null)
super.setValue(initialVal)
private val mPending = AtomicBoolean(false)
@MainThread
override fun observe(owner: LifecycleOwner, observer: Observer<in T?>)
if (hasActiveObservers())
Log.w(TAG, "Multiple observers registered but only one will be notified of changes.")
// Observe the internal MutableLiveData
super.observe(owner, t ->
if (mPending.compareAndSet(true, false))
observer.onChanged(t)
)
@MainThread
override fun setValue(t: T?)
mPending.set(true)
super.setValue(t)
/**
* Used for cases where T is Void, to make calls cleaner.
*/
@MainThread
fun call()
value = null
companion object
private const val TAG = "SingleLiveEvent"
【讨论】:
以上是关于当我在 LiveData 观察者中使用 navController 时,Android Navigation 组件图停止正常工作的主要内容,如果未能解决你的问题,请参考以下文章
如何在 MVVM 架构中观察 RecyclerView 适配器中的 LiveData?
在 xml 中设置/观察 livedata 的正确方法是啥?调用观察者方法失败
如何在MVVM架构中观察RecyclerView适配器中的LiveData?