如何解决从LiveData观察器调用时,导航组件的默认后退堆栈不起作用
我正在将Android导航组件与一个导航抽屉一起使用(就像Android Studio模板一样)。我将片段A,B,C用作导航抽屉中的顶级片段,并将片段Z与导航图中的片段A连接起来。现在我在片段A中有一个按钮。单击该按钮将使用Safe args打开片段Z。
binding.button.setOnClickListener {
val action = NewsFragmentDirections.actionNavNewsToNewsDetailsFragment()
it.findNavController().navigate(action)
}
打开片段Z后,应用程序栏图标将自动更改为返回按钮,这使我可以返回片段A。
这些工作正常,但是这个问题是,当我在实时数据观察者中使用相同的安全args代码时,后退按钮不起作用。
viewModel.actionNewsDetails.observe(viewLifecycleOwner,{
val action = NewsFragmentDirections.actionNavNewsToNewsDetailsFragment()
findNavController().navigate(action)
})
以下是一些其他详细信息
- 一旦进入片段Z,它将像往常一样显示向后导航,但是仅单击它不会执行任何操作
- 当我快速单击“后退”按钮几次时,我注意到应用栏标题闪烁(在片段A和Z之间切换)
- 当我进入片段Z时,可以通过滑动来打开Nav抽屉
- 我的实时数据代码写在片段A的onCreateView()
- 实时数据是通过ViewModel中的函数触发的
我一直在努力解决这个问题。对不起,我的英语不好。
解决方法
接下来的信息非常重要:
当我快速单击后退按钮几次时,我注意到应用程序栏标题闪烁(在片段A和Z之间切换)
我很确定会发生什么,片段Z中的后退按钮正常工作,片段A显示,并且liveData再次被触发并再次导航到片段Z。这发生得非常快,但是正如您所指出的,当您很快就可以看到延迟。
解决方案:在LiveData观察器中导航到片段Z之前,请更改liveData的值,以便当您返回片段A时,它不会再次触发。
这个问题使我几周前失去了一个小时。
编辑26/10/2020 :
要解决该问题,请实现SingleLiveEvent
类,并改用MutableLiveData
。
SingleLiveEvent.class
/**
* A lifecycle-aware observable that sends only new updates after subscription,used for events like
* navigation and Snackbar messages.
* <p>
* This avoids a common problem with events: on configuration change (like rotation) an update
* can be emitted if the observer is active. This LiveData only calls the observable if there's an
* explicit call to setValue() or call().
* <p>
* Note that only one observer is going to be notified of changes.
*/
public class SingleLiveEvent<T> extends MutableLiveData<T> {
private static final String TAG = "SingleLiveEvent";
private final AtomicBoolean mPending = new AtomicBoolean(false);
@MainThread
public void observe(LifecycleOwner owner,final Observer<? super T> observer) {
if (hasActiveObservers()) {
Log.w(TAG,"Multiple observers registered but only one will be notified of changes.");
}
// Observe the internal MutableLiveData
super.observe(owner,new Observer<T>() {
@Override
public void onChanged(@Nullable T t) {
if (mPending.compareAndSet(true,false)) {
observer.onChanged(t);
}
}
});
}
@MainThread
public void setValue(@Nullable T t) {
mPending.set(true);
super.setValue(t);
}
/**
* Used for cases where T is Void,to make calls cleaner.
*/
@MainThread
public void call() {
setValue(null);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。