Android LiveData会在订阅时阻止接收最后一个值

时间:2018-04-14 14:56:33

标签: android android-architecture-components android-livedata mutablelivedata

是否可以防止LiveData在开始观察时收到最后一个值? 我正在考虑将LiveData用作事件。

例如show message,导航事件或对话框触发器等事件,类似于EventBus。

我找到了类似And the result of command 'wc'的东西 - 但它只适用于1个观察者,而不适用于多个观察者。

12 个答案:

答案 0 :(得分:3)

我认为在开始观察是否按原样使用LiveData时,无法防止LiveData接收到最后一个值。您可以做的是扩展ViewModel,并使其仅在添加观察者的情况下通知视图。

另一种选择是仅忽略回调

  1. 向ViewModel添加一个标志。

    private boolean isFirstTime = true;
    
    public boolean getIsFirstTime() { return isFirstTime; }
    
    public boolean onObserverAdded() { isFirstTime = false; }`
    
  2. 在回调中添加检查

    @Override
    public void onChanged(@Nullable final String newName) {
    boolean ignore = ((MyViewModel)ViewModelProviders.of(MyActivity.this).get(MyViewModel.class)).getIsFirstTime();
    if(ignore) return;
    
    // Update the UI
    }
    
  3. 添加观察者后最后调用onObserverAdded()

答案 1 :(得分:2)

我对RxJava有一定的经验,已经习惯于认为这种行为要求通常是Observeable(在我们的案例中是LiveData)的关注。与operators之类的replay()相比,有很多gist可以控制与用户实际发布的内容相比实际发出的内容(以及发出的时间)。本质上,SingleLiveEvent也具有相同的概念。

因此,我想到了MutableLiveData的这种经过修改的实现,称为VolatileLiveData

open class VolatileLiveData<T> : MutableLiveData<T>() {
    private val lastValueSeq = AtomicInteger(0)
    private val wrappers = HashMap<Observer<in T>, Observer<T>>()

    @MainThread
    public override fun setValue(value: T) {
        lastValueSeq.incrementAndGet()
        super.setValue(value)
    }

    @MainThread
    public override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
        val observerWrapper = ObserverWrapper(lastValueSeq, observer)
        wrappers[observer] = observerWrapper
        super.observe(owner, observerWrapper)
    }

    @MainThread
    public override fun observeForever(observer: Observer<in T>) {
        val observerWrapper = ObserverWrapper(lastValueSeq, observer)
        wrappers[observer] = observerWrapper
        super.observeForever(observerWrapper)
    }

    @MainThread
    public override fun removeObserver(observer: Observer<in T>) {
        val observerWrapper = wrappers[observer]
        observerWrapper?.let {
            wrappers.remove(observerWrapper)
            super.removeObserver(observerWrapper)
        }
    }
}

private class ObserverWrapper<T>(private var currentSeq: AtomicInteger, private val observer: Observer<in T>) : Observer<T> {
    private val initialSeq = currentSeq.get()
    private var _observer: Observer<in T> = Observer {
        if (currentSeq.get() != initialSeq) {
            // Optimization: this wrapper implementation is only needed in the beginning.
            // Once a valid call is made (i.e. with a different concurrent sequence), we
            // get rid of it any apply the real implementation as a direct callthrough.
            _observer = observer
            _observer.onChanged(it)
        }
    }

    override fun onChanged(value: T) {
        _observer.onChanged(value)
    }
}

首先,类似于@emandt,我已将唯一序列与每个实时值相关联-但严格地在实时数据本身的范围内。每当为实时数据设置值时,都会设置此顺序。

第二,受SingleLiveData的启发,我在用户的观察者周围引入了包装器,这些包装器仅在顺序不同的情况下才调用该包装器(即,自订阅以来已设置 new 值)制成)。

基本上是总结,但有关完整文档,请转到我的{{3}}。

用法

关于使用它-如果您完全控制LiveData,请像使用VolatileLiveData一样简单地使用MutableLiveData。如果数据最初来自其他地方(例如房间),则可以使用Transformations.switchMap()来“切换”到 volatile 实现。

答案 2 :(得分:2)

面对同样的问题,我创建了一些简单的kotlin扩展函数,可以轻松解决问题。

用法如下:

val liveData = MutableLiveData<String>()
liveData.value = "Hello"

val freshResult = mutableListOf<String>()
val normalResult = mutableListOf<String>()

liveData.observeForeverFreshly(Observer {
    freshResult.add(it)
})

liveData.observeForever(Observer {
    normalResult.add(it)
})

liveData.value = "World"

assertEquals(listOf("World"), freshResult)
assertEquals(listOf("Hello", "World"), normalResult)

基本源代码被解释为“ bllow”。

有关更多详细信息(以支持某些特殊情况,例如从Transformations.map返回的MediatorLiveData),可以在github中查看它:livedata-ext

FreshLiveData.kt

fun <T> LiveData<T>.observeFreshly(owner: LifecycleOwner, observer: Observer<in T>) { 
    // extention fuction to get LiveData's version, will explain in below.
    val sinceVersion = this.version()
    this.observe(owner, FreshObserver<T>(observer, this, sinceVersion))
}

fun <T> LiveData<T>.observeForeverFreshly(observer: Observer<in T>, skipPendingValue: Boolean = true) {
    val sinceVersion = this.version()
    this.observeForever(FreshObserver<T>(observer, this, sinceVersion))
}

// Removes the observer which has been previously observed by [observeFreshly] or [observeForeverFreshly].
fun <T> LiveData<T>.removeObserverFreshly(observer: Observer<in T>) {
    this.removeObserver(FreshObserver<T>(observer, this, 0))
}

class FreshObserver<T>(
    private val delegate: Observer<in T>,
    private val liveData: LiveData<*>,
    private val sinceVersion: Int
) : Observer<T> {

    override fun onChanged(t: T) {
        if (liveData.version() > sinceVersion) {
            delegate.onChanged(t)
        }
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false
        other as FreshObserver<*>
        if (delegate != other.delegate) return false
        return true
    }

    override fun hashCode(): Int {
        return delegate.hashCode()
    }
}

因为我们需要访问LiveData的pcakage可见方法getVersion()进行比较,所以请在包android.arch.lifecycleandroidx.lifecycle(AndroidX)中​​创建一个类:

LiveDataHiddenApi.kt

package androidx.lifecycle

fun LiveData<*>.version(): Int {
    return this.getVersion()
}

答案 3 :(得分:2)

I`m using this EventWraper class from Google Samples inside MutableLiveData

/**
 * Used as a wrapper for data that is exposed via a LiveData that represents an event.
 */
public class Event<T> {

    private T mContent;

    private boolean hasBeenHandled = false;


    public Event( T content) {
        if (content == null) {
            throw new IllegalArgumentException("null values in Event are not allowed.");
        }
        mContent = content;
    }

    @Nullable
    public T getContentIfNotHandled() {
        if (hasBeenHandled) {
            return null;
        } else {
            hasBeenHandled = true;
            return mContent;
        }
    }

    public boolean hasBeenHandled() {
        return hasBeenHandled;
    }
}

In ViewModel :

 /** expose Save LiveData Event */
 public void newSaveEvent() {
    saveEvent.setValue(new Event<>(true));
 }

 private final MutableLiveData<Event<Boolean>> saveEvent = new MutableLiveData<>();

 LiveData<Event<Boolean>> onSaveEvent() {
    return saveEvent;
 }

In Activity/Fragment

mViewModel
    .onSaveEvent()
    .observe(
        getViewLifecycleOwner(),
        booleanEvent -> {
          if (booleanEvent != null)
            final Boolean shouldSave = booleanEvent.getContentIfNotHandled();
            if (shouldSave != null && shouldSave) saveData();
          }
        });

答案 4 :(得分:2)

根据jurij-pitulja的答案。

如果我们使用kotlin coroutines,则解决方案如下所示。

class Event<T>(private val content: T) {

    var isHandled = false
    private set

    fun getContentIfNotHandled(): T? {
        return takeIf { !isHandled }?.let {
            isHandled = true
            content
        }
    }
}

view model类内部,将Flow.asLiveData()替换为emit new Event

val authResult: LiveData<Event<Result<AuthResponse>>> = _emailLiveData.switchMap { email ->
    liveData{
        repository.authRequest(email).collect{
            emit(Event(it))
        }
    }
}

observer内实现fragment方法

viewModel.authResult.observe(viewLifecycleOwner){
            it.getContentIfNotHandled()?.run {
                onAuthRequestComplete(this)
            }
        }

答案 5 :(得分:1)

我创建了一个新类,该类将保存我的真实数据和一个“特殊ID”:

class LiveDataItem {
    long mRealtimeNanos;
    YOUR_PREVIOUS_LIVEDATA_TYPE mData;
    LiveDataItem(YOUR_PREVIOUS_LIVEDATA_TYPE data, long realtimeNanos) {
        this.mRealtimeNanos = realtimeNanos;
        this.mData = data;
    }
}

然后我创建了一个新的“全局”变量:

final List<Long> mExcludedRealtimeNanos = new ArrayList<>;

这时,我选择通过新的自定义“ postValue()”方法设置“ LiveDataItem”类型的“ set / postValue()”,而不是原始的“ YOUR_PREVIOUS_LIVEDATA_TYPE”类型:

public void myPostValue(YOUR_PREVIOUS_LIVEDATA_TYPE data, boolean notifyWhenObserved) {
    long cRealtimeNanos = SystemClock.realtimeNanos();
    if (!notifyWhenObserved) mExcludedRealtimeNanos.add(cRealtimeNanos);
    ....postValue(new LiveDataItem(data, cRealtimeNanos));
}

然后,我创建了一个普通的观察器,该观察器将接收所有“ Changed()”事件,并在其中放入有关“ RealtimeNanos”的检查:

public void onChanged(LiveDataItem myDataItem) {
    boolean cFound = false;
    for (Long cRealtimeNanos : mExcludedRealtimeNanos) {
        if (cRealtimeNanos == myDataItem.mRealtimeNanos) {
            cFound = true;
            break;
        }
    }
    //check if it was found --> NO: it means that I wish to get the notification
    if (!cFound) mMyOnChangedCallback(myDataItem.mData)
}

很明显,“ mMyOnChangedCallback()”方法是一个回调函数,只有当您设置在数据创建期间通知它时,才会在原始“ onChanged()”事件发生时调用该函数。

您可以选择再次接收通知,方法是从“ mExcludedRealtimeNanos”中删除THAT RealtimeNanos,然后将新的Observer附加到该LiveData。

很少有更改可以改进此代码,但是我写了一些我记得的旧代码(目前我不在电脑旁)。例如,当使用自定义postValue()方法发布新数据时,我们可以决定从“ mExcludedRealtimeNanos”中删除一个值。...

答案 6 :(得分:1)

即使我有相同的要求。我通过扩展MutableLiveData实现了这一点

package com.idroidz.android.ion.util;    
import android.arch.lifecycle.LifecycleOwner;
import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.Observer;
import android.support.annotation.MainThread;
import android.support.annotation.Nullable;

import java.util.concurrent.atomic.AtomicBoolean;

public class VolatileMutableLiveData<T> extends MutableLiveData<T> {


    private final AtomicBoolean mPending = new AtomicBoolean(false);

    @MainThread
    public void observe(LifecycleOwner owner, final Observer<T> observer) {
        // Observe the internal MutableLiveData
        mPending.set(false);
        super.observe(owner, new Observer<T>() {
            @Override
            public void onChanged(@Nullable T t) {
                if (mPending.get()) {
                    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);
    }

    public void callFromThread() {
        super.postValue(null);
    }
}

答案 7 :(得分:1)

我创建了一个LiveData对象FreshLiveData,该对象仅在调用onChangesetValue后才向观察者发出postValue

FreshLiveData.kt

/**
 * A lifecycle-aware observable that emits only new data after subscription. Any data that has
 * already been set, before the observable has subscribed, will be ignored.
 *
 * This avoids a common problem with events: on configuration change (like rotation, font change) 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 postValue().
 *
 * All observers will be notified of change(s).
 */
class FreshLiveData<T> : MutableLiveData<T>() {

    private val observers = mutableMapOf<LifecycleOwner, FreshLiveDataObserver>()

    override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
        @Suppress("UNCHECKED_CAST")
        observer as Observer<T>
        observers[owner].apply {
            if (this == null) {
                observers[owner] = FreshLiveDataObserver(observer).apply {
                    super.observe(owner, this)
                }
            } else {
                add(observer)
            }
        }
    }

    override fun observeForever(observer: Observer<in T>) {
        @Suppress("UNCHECKED_CAST")
        observer as Observer<T>
        observers[ProcessLifecycleOwner.get()].apply {
            if (this == null) {
                observers[ProcessLifecycleOwner.get()] = FreshLiveDataObserver(observer).apply {
                    super.observeForever(this)
                }
            } else {
                add(observer)
            }
        }
    }

    override fun removeObservers(owner: LifecycleOwner) {
        observers.remove(owner)
        super.removeObservers(owner)
    }

    override fun removeObserver(observer: Observer<in T>) {
        @Suppress("UNCHECKED_CAST")
        observers.forEach { it.value.remove(observer as Observer<T>) }
        super.removeObserver(observer)
    }

    @MainThread
    override fun setValue(t: T?) {
        observers.forEach { it.value.setPending() }
        super.setValue(t)
    }

    override fun postValue(value: T) {
        observers.forEach { it.value.setPending() }
        super.postValue(value)
    }

    inner class FreshLiveDataObserver(observer: Observer<T>) : Observer<T> {
        private val observers = mutableSetOf<Observer<T>>()
        private val pending = AtomicBoolean(false)

        init {
            observers.add(observer)
        }

        fun add(observer: Observer<T>) = observers.add(observer)
        fun remove(observer: Observer<T>) = observers.remove(observer)
        fun setPending() = pending.set(true)

        override fun onChanged(t: T) {
            if (pending.compareAndSet(true, false)) {
                observers.forEach { observer ->
                    observer.onChanged(t)
                }
            }
        }

    }
}

这是将现有的LiveData转换为FreshLiveData的扩展。

LiveDataExtensions.kt

@MainThread
fun <T> LiveData<T>.toFreshLiveData(): LiveData<T> {
    val freshLiveData = FreshLiveData<T>()
    val output = MediatorLiveData<T>()
    // push any onChange from the LiveData to the FreshLiveData
    output.addSource(this) { liveDataValue -> freshLiveData.value = liveDataValue }
    // then push any onChange from the FreshLiveData out
    output.addSource(freshLiveData) { freshLiveDataValue -> output.value = freshLiveDataValue }
    return output
}

用法:

val liveData = MutableLiveData<Boolean>()
liveData.value = false
liveData.toFreshLiveData().observeForever {
    // won't get called with `it = false` because the observe was setup after setting that livedata value
    // will get called with `it = true` because the observer was setup before setting that livedata value
}
liveData.value = false

val freshLiveData = FreshLiveData<Boolean>()
freshLiveData.value = false
freshLiveData.observeForever {
    // won't get called with `it = false` because the observe was setup after setting that livedata value
    // will get called with `it = true` because the observer was setup before setting that livedata value
}
freshLiveData.value = true

答案 8 :(得分:1)

没有理由不使用LiveData。如果您需要一个单独的行为(某种东西不会保留以前的值),那么您应该使用一个不能保留以前的值的组件-而不是乱砍它(“记住”它已经发出并忘记了)发射等等)

您可以添加event-emitter库:

implementation 'com.github.Zhuinden:live-event:1.1.0'

来自Jitpack:maven { url "https://jitpack.io" }

那你就可以做

private val eventEmitter = EventEmitter<WordController.Events>()
val controllerEvents: EventSource<WordController.Events> = eventEmitter

controllerEvents.observe(viewLifecycleOwner) { event: WordController.Events ->
    when (event) {
        is WordController.Events.NewWordAdded -> showToast("Added ${event.word}")
    }.safe()
}

答案 9 :(得分:1)

您可以使用this文章中所述的EventLiveData。与SingleLiveData一样,它是LiveData扩展,但支持多个观察者。当观察者应该接收事件时,还允许自定义生命周期限制。例如,如果您不想在片段处于后台时接收事件。

EventLiveData拥有内部观察者,该观察者可以永远观察,而覆盖了使用observe方法将观察者保存到内部地图中,而绕过了本机LiveData事件分配机制。

public  class EventLiveData<T> extends LiveData<T> {

private final HashMap<Observer<? super T>, EventObserverWrapper> observers= new HashMap<>();
private final Observer<T> internalObserver;
int mActiveCount = 0;

public EventLiveData() {
    this.internalObserver =  (new Observer<T>() {
        @Override
        public void onChanged(T t) {
            Iterator<Map.Entry<Observer<? super T>, EventObserverWrapper>> iterator = EventLiveData.this.observers.entrySet().iterator();
            while (iterator.hasNext()){
                EventObserverWrapper wrapper= iterator.next().getValue();
                if(wrapper.shouldBeActive())
                    wrapper.getObserver().onChanged(t);
            }
        }
    });
}
private void internalObserve(){
    super.observeForever(this.internalObserver);

}
@MainThread
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
    observe(owner, observer,STARTED,null);
}
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer, @NonNull Lifecycle.State minimumStateForSendingEvent) {
    observe(owner, observer,minimumStateForSendingEvent,null);
}
@MainThread
public void observeInOnStart(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
    observe(owner, observer,STARTED, Lifecycle.Event.ON_STOP);
}
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer, @NonNull Lifecycle.State minimumStateForSendingEvent, Lifecycle.Event removeObserverEvent) {
    assertMainThread("observe");
    assertNotNull(owner, "owner");
    assertNotNull(observer, "observer");
    assertNotNull(owner, "minimumStateForSendingEvent");
    assertDestroyedState(minimumStateForSendingEvent);
    assertMaximumEvent(removeObserverEvent);
    if(minimumStateForSendingEvent==DESTROYED){
        StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
        StackTraceElement caller = stackTraceElements[3];
        String className = caller.getClassName();
        String methodName = caller.getMethodName();
        IllegalArgumentException exception =
                new IllegalArgumentException("State can not be equal to DESTROYED! : " +
                        "method " + className + "." + methodName +
                        ", parameter " + minimumStateForSendingEvent);
        throw sanitizeStackTrace(exception);
    }

    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        return;
    }

    EventLifecycleBoundEventObserver wrapper = new EventLifecycleBoundEventObserver(owner, observer);
    wrapper.setMinimumStateForSendingEvent(minimumStateForSendingEvent);
    wrapper.setMaximumEventForRemovingEvent(removeObserverEvent);
    EventObserverWrapper existing = wrapper;
    if(!observers.containsKey(observer))existing = observers.put(observer, wrapper);
    if (existing != null && !existing.isAttachedTo(owner)) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    if (existing != null) {
        return;
    }
    owner.getLifecycle().addObserver(wrapper);

    if (!super.hasObservers()) {
        internalObserve();
    }

}
@MainThread
@Override
public void observeForever(@NonNull Observer observer) {
    assertMainThread("observeForever");
    assertNotNull(observer, "observer");
    EventAlwaysActiveEventObserver wrapper = new EventAlwaysActiveEventObserver(observer);
    EventObserverWrapper existing = wrapper;
    if(!observers.containsKey(observer))existing = observers.put(observer, wrapper);
    if (existing != null && existing instanceof EventLiveData.EventLifecycleBoundEventObserver) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    if (existing != null) {
        return;
    }
    if (!super.hasObservers()) {
        internalObserve();
    }
    wrapper.activeStateChanged(true);
}
/**
 {@inheritDoc}
 */
@Override
public void removeObservers(@NonNull  LifecycleOwner owner) {
    assertMainThread("removeObservers");
    assertNotNull(owner, "owner");
    Iterator<Map.Entry<Observer<? super T>, EventObserverWrapper>> iterator = EventLiveData.this.observers.entrySet().iterator();
    while (iterator.hasNext()){
        Map.Entry<Observer<? super T>, EventObserverWrapper> entry=iterator.next();
        if(entry.getValue() instanceof EventLiveData.EventLifecycleBoundEventObserver){
            EventLifecycleBoundEventObserver eventLifecycleBoundObserver =(EventLifecycleBoundEventObserver) entry.getValue();
            if(eventLifecycleBoundObserver.isAttachedTo(owner))this.observers.remove(entry.getKey());
        }
    }
}
@Override
public void removeObserver(@NonNull Observer observer) {
    assertMainThread("removeObserver");
    assertNotNull(observer, "observer");
    this.observers.remove(observer);

}
final protected void onActive() {}
protected void onActiveEvent() {}
protected void onInactive() {

}
@SuppressWarnings("WeakerAccess")
public boolean hasObservers() {
    return observers.size() > 0;
}
@SuppressWarnings("WeakerAccess")
public boolean hasActiveObservers() {
    return mActiveCount > 0;
}
class EventLifecycleBoundEventObserver extends EventObserverWrapper implements LifecycleObserver {
    @NonNull
    private final LifecycleOwner mOwner;
    private Lifecycle.State MINIMUM_STATE_FOR_SENDING_EVENT= STARTED;
    private Lifecycle.Event MAXIMUM_EVENT_FOR_REMOVING_EVENT= null;
    EventLifecycleBoundEventObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
        super(observer);
        mOwner = owner;
    }

    public Lifecycle.State getMinimumStateForSendingEvent() {
        return MINIMUM_STATE_FOR_SENDING_EVENT;
    }

    public Lifecycle.Event getMaximumStateForRemovingEvent() {
        return MAXIMUM_EVENT_FOR_REMOVING_EVENT;
    }

    public void setMaximumEventForRemovingEvent(Lifecycle.Event MAXIMUM_EVENT_FOR_REMOVING_EVENT) {
        this.MAXIMUM_EVENT_FOR_REMOVING_EVENT = MAXIMUM_EVENT_FOR_REMOVING_EVENT;
    }

    public void setMinimumStateForSendingEvent(Lifecycle.State MINIMUM_STATE_FOR_SENDING_EVENT) {
        this.MINIMUM_STATE_FOR_SENDING_EVENT = MINIMUM_STATE_FOR_SENDING_EVENT;
    }

    @Override
    boolean shouldBeActive() {
        Lifecycle.State state=mOwner.getLifecycle().getCurrentState();
        return state.isAtLeast(MINIMUM_STATE_FOR_SENDING_EVENT);
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED||(MAXIMUM_EVENT_FOR_REMOVING_EVENT!=null&&MAXIMUM_EVENT_FOR_REMOVING_EVENT==event)) {
            removeObserver(mObserver);
            return;
        }
        activeStateChanged(shouldBeActive());
    }
    @Override
    boolean isAttachedTo(LifecycleOwner owner) {
        return mOwner == owner;
    }
    @Override
    void detachObserver() {
        mOwner.getLifecycle().removeObserver(this);
    }
}

private abstract class EventObserverWrapper {
    protected final Observer<? super T> mObserver;
    boolean mActive;
    EventObserverWrapper(Observer<? super T> observer) {
        mObserver = observer;
    }
    abstract boolean shouldBeActive();

    boolean isAttachedTo(LifecycleOwner owner) {
        return false;
    }
    void detachObserver() {
    }
    public Observer<? super T> getObserver() {
        return mObserver;
    }
    void activeStateChanged(boolean newActive) {
        if (newActive == mActive) {
            return;
        }
        // immediately set active state, so we'd never dispatch anything to inactive
        // owner
        mActive = newActive;
        boolean wasInactive = EventLiveData.this.mActiveCount == 0;
        EventLiveData.this.mActiveCount += mActive ? 1 : -1;
        if (wasInactive && mActive) {
            onActiveEvent();
        }
        if (EventLiveData.this.mActiveCount == 0 && !mActive) {
            onInactive();
        }
    }
}

private class EventAlwaysActiveEventObserver extends EventObserverWrapper {

    EventAlwaysActiveEventObserver(Observer<? super T> observer) {
        super(observer);
    }
    @Override
    boolean shouldBeActive() {
        return true;
    }
}
private void assertDestroyedState(@NonNull Lifecycle.State minimumStateForSendingEvent){
    if(minimumStateForSendingEvent==DESTROYED){
        StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
        StackTraceElement caller = stackTraceElements[3];
        String className = caller.getClassName();
        String methodName = caller.getMethodName();
        IllegalArgumentException exception =new IllegalArgumentException("State can not be equal to "+ minimumStateForSendingEvent +"method " + className + "." + methodName +", parameter   minimumStateForSendingEvent");
        throw sanitizeStackTrace(exception);}
}
private void assertMaximumEvent(@NonNull Lifecycle.Event maximumEventForRemovingEvent){
    if(maximumEventForRemovingEvent== Lifecycle.Event.ON_START||maximumEventForRemovingEvent== Lifecycle.Event.ON_CREATE
            ||maximumEventForRemovingEvent== Lifecycle.Event.ON_RESUME){
        StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
        StackTraceElement caller = stackTraceElements[3];
        String className = caller.getClassName();
        String methodName = caller.getMethodName();
        IllegalArgumentException exception = new IllegalArgumentException("State can not be equal to "+maximumEventForRemovingEvent +  "method " + className + "." + methodName +", parameter  maximumEventForRemovingEvent" );
        throw sanitizeStackTrace(exception);
    }
}
private  void assertMainThread(String methodName) {
    boolean isUiThread = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? Looper.getMainLooper().isCurrentThread() : Thread.currentThread() == Looper.getMainLooper().getThread();
    if (!isUiThread) {throw new IllegalStateException("Cannot invoke " + methodName + " on a background"+ " thread"); }
}
private  void assertNotNull(Object value, String paramName) {
    if (value == null) {throwParameterIsNullException(paramName); } }
private  void throwParameterIsNullException(String paramName) {
    StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
    StackTraceElement caller = stackTraceElements[3];
    String className = caller.getClassName();
    String methodName = caller.getMethodName();
    IllegalArgumentException exception =
            new IllegalArgumentException("Parameter specified as non-null is null: " +
                    "method " + className + "." + methodName +
                    ", parameter " + paramName);
    throw sanitizeStackTrace(exception);
}
private   <T extends Throwable> T sanitizeStackTrace(T throwable) { return sanitizeStackTrace(throwable, this.getClass().getName());}
<T extends Throwable> T sanitizeStackTrace(T throwable, String classNameToDrop) {
    StackTraceElement[] stackTrace = throwable.getStackTrace();
    int size = stackTrace.length;
    int lastIntrinsic = -1;
    for (int i = 0; i < size; i++) {
        if (classNameToDrop.equals(stackTrace[i].getClassName())) {lastIntrinsic = i; } }
    StackTraceElement[] newStackTrace = Arrays.copyOfRange(stackTrace, lastIntrinsic + 1, size);
    throwable.setStackTrace(newStackTrace);
    return throwable;
}

}

答案 10 :(得分:1)

更简单的解决方案是使用EventLiveData lib:

implementation 'com.rugovit.eventlivedata:eventlivedata:1.0'

MutableEventLiveData<String>  eventLiveData =new MutableEventLiveData<>(); 
viewModel.event.observe(this, Observer {
    // ...
})
 

您可以像常规实时数据一样使用它。它是livedata的扩展,并支持livedata的所有功能。 与其他解决方案不同,它支持多个观察者。

Github链接:https://github.com/rugovit/EventLiveData

答案 11 :(得分:0)

在调用android.arch.lifecycle.LiveData#observe函数之前只需忽略数据。

class IgnoreHistoryLiveData<T> : MutableLiveData<T>() {
    private val unactivedObservers = LinkedBlockingQueue<WrapperObserver<T>>()
    override fun observe(owner: LifecycleOwner, observer: Observer<T>) {
        val wo = WrapperObserver<T>(observer)
        unactivedObservers.add(wo)
        super.observe(owner, wo)
    }


    override fun setValue(value: T) {
        while (unactivedObservers.isNotEmpty()) {
            unactivedObservers.poll()?.actived = true
        }
        super.setValue(value)
    }
}

private class WrapperObserver<T>(private val origin: Observer<T>) : Observer<T> {
    var actived = false
    override fun onChanged(t: T?) {
        if (actived) {
            origin.onChanged(t)
        }
    }
}