From eca4e6bdcbc6eabb615697078d9b75d73f20f52d Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Sun, 29 Nov 2020 23:59:12 +0100 Subject: [PATCH] Add SingleLiveData utility class --- .../android/ui/base/SingleLiveEvent.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 app/src/main/java/org/mercury_im/messenger/android/ui/base/SingleLiveEvent.java diff --git a/app/src/main/java/org/mercury_im/messenger/android/ui/base/SingleLiveEvent.java b/app/src/main/java/org/mercury_im/messenger/android/ui/base/SingleLiveEvent.java new file mode 100644 index 0000000..879bdf4 --- /dev/null +++ b/app/src/main/java/org/mercury_im/messenger/android/ui/base/SingleLiveEvent.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.mercury_im.messenger.android.ui.base; + +import android.util.Log; + +import androidx.annotation.MainThread; +import androidx.annotation.NonNull; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.Observer; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * A lifecycle-aware observable that sends only new updates after subscription, used for events like + * navigation and Snackbar messages. + *

+ * 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(). + *

+ * Note that only one observer is going to be notified of changes. + */ +public class SingleLiveEvent extends MutableLiveData { + + private static final String TAG = "SingleLiveEvent"; + + private final AtomicBoolean pending = new AtomicBoolean(false); + + @Override + @MainThread + public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) { + if (hasActiveObservers()) { + Log.w(TAG, "Multiple observers registered but only one will be notified of changes."); + } + + super.observe(owner, new Observer() { + @Override + public void onChanged(T t) { + if (pending.compareAndSet(true, false)) { + observer.onChanged(t); + } + } + }); + } + + @Override + @MainThread + public void setValue(T value) { + pending.set(true); + super.setValue(value); + } + + /** + * Used for cases where T is Void, to make calls cleaner. + */ + @MainThread + public void call() { + setValue(null); + } +}