Has*_*tty 3 android kotlin android-jetpack android-architecture-navigation
我正在使用带有导航抽屉的 Android 导航组件(如在 Android Studio 模板中)。我将片段 A、B、C 作为顶级片段,用于导航抽屉中,片段 Z 与导航图中的片段 A 相连。现在我在片段 A 中有一个按钮。单击该按钮将使用安全参数打开片段 Z。
binding.button.setOnClickListener {
val action = NewsFragmentDirections.actionNavNewsToNewsDetailsFragment()
it.findNavController().navigate(action)
}
Run Code Online (Sandbox Code Playgroud)
打开片段 Z 时,应用栏图标会自动变为后退按钮,这将允许我返回片段 A。
这些工作正常,但这个问题是,当我在实时数据 obsedrver 中使用相同的安全参数代码时,后退按钮不起作用。
viewModel.actionNewsDetails.observe(viewLifecycleOwner, {
val action = NewsFragmentDirections.actionNavNewsToNewsDetailsFragment()
findNavController().navigate(action)
})
Run Code Online (Sandbox Code Playgroud)
这里有一些额外的细节
我一直在努力解决这个问题。对不起,我的英语不好。
接下来的信息非常重要:
当我快速点击后退按钮几次时,我注意到应用栏标题闪烁(在片段 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);
}
}
Run Code Online (Sandbox Code Playgroud)
科特林版
class SingleLiveEvent<T> : MutableLiveData<T>() {
val TAG: String = "SingleLiveEvent"
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, Observer<T> { t ->
if (mPending.compareAndSet(true, false)) {
observer.onChanged(t)
}
})
}
@MainThread
override fun setValue(@Nullable t: T?) {
mPending.set(true)
super.setValue(t)
}
/**
* Used for cases where T is Void, to make calls cleaner.
*/
@MainThread
fun call() {
value = null
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
934 次 |
| 最近记录: |