Вызывайте обратный вызов LiveData.observe () только для измененных данных и игнорируйте изменения жизненного цикла контроллера (Activity / Fragment) - PullRequest
0 голосов
/ 27 сентября 2019

Я использую LiveData для публикации сообщений об ошибках на контроллере (Activity / Fragment).

После установки сообщения об ошибке (MutableLiveData.setValue(...)) значение сообщения об ошибке отслеживаетсяобратный вызов (MutableLiveData.observe(lifecycleOwner, callback)), который показывает сообщение в Snackbar компоненте пользовательского интерфейса.

Snackbar по своей конструкции виден только в течение короткого периода времени, что вполне нормально.После того, как Snackbar скрыт, я хочу сохранить его таким образом.

Однако после того, как пользователь поворачивает дисплей, контроллер (Activity / Fragment) воссоздается, и наблюдатель снова получает уведомление -поэтому Snackbar появляется снова, а это не то, что я хочу.

Вопрос: Я как-то исправил поведение с помощью if(!isActivityRecreated()) { showSnackbar(...); }, но мне интересно, есть ли способ сказать MutableLiveData случай, когда наблюдатель должен вызываться только при изменении данных и, следовательно, игнорировать изменения жизненного цикла контроллера?

(Изменить)

Ответ от @nik: https://medium.com/androiddevelopers/livedata-with-snackbar-navigation-and-other-events-the-singleliveevent-case-ac2622673150

Последующее обсуждение: https://proandroiddev.com/livedata-with-single-events-2395dea972a8

Библиотека "LiveEvent": Вот всеобъемлющая реализация SingleLiveEvent предложено автором в первой ссылке: https://github.com/hadilq/LiveEvent. Эта реализация выглядит очень надежной по сравнению с остальными решениями.Поддерживает несколько подписок и является потокобезопасным.

1 Ответ

0 голосов
/ 27 сентября 2019

Как отметил @Michal Vician в комментарии, я просто уточняю ответ.Вы должны просто расширить MutableLiveData, как показано ниже.

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<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);
}

}

ссылка находится здесь

...