接下来的信息非常重要:
当我快速单击后退按钮几次时,我注意到应用程序栏标题闪烁(在片段 A 和 Z 之间变化)
我很确定发生的情况是,片段 Z 中的后退按钮工作正常,片段 A 显示,它的 liveData 再次触发并再次导航到片段 Z。这种情况发生得非常快,但正如您所指出的,当您执行此操作时非常快,你可以看到延迟。
解决方案:在 LiveData 观察器中导航到片段 Z 之前,更改 liveData 的值,这样当您返回到片段 A 时,它就不会再次触发。
这个问题几周前就让我损失了一个小时。
编辑 2020年10月26日:
为了解决这个问题,实施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);
}
}
科特林版本
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
}
}