LiveData 防止在开始观察时收到最后一个值

Posted

技术标签:

【中文标题】LiveData 防止在开始观察时收到最后一个值【英文标题】:LiveData prevent receive the last value when start observing 【发布时间】:2018-09-24 17:53:42 【问题描述】:

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

例如显示消息、导航事件或对话触发器等事件,类似于EventBus

ViewModel 和 Fragment 之间的通信问题,Google 给了我们LiveData 用数据更新视图,但是这种类型的通信不适合我们只需要用单个事件更新视图一次,我们也不能在ViewModel 中保留视图的引用并调用一些方法,因为它会造成内存泄漏。

我发现了类似的 SingleLiveEvent - 但它仅适用于 1 个观察者,而不适用于多个观察者。

---更新----

正如@EpicPandaForce 所说“没有理由将 LiveData 用作它不是的东西”,问题的意图可能是Communication between view and ViewModel in MVVM with LiveData

【问题讨论】:

嗨,你能澄清你问题中的第二句话吗?你到底想达到什么目标? 消息、导航事件或对话触发器等事件。类似于 EventBus 我一直在为同样的问题苦苦挣扎,但我终其一生都找不到关于它的好信息。我真的很高兴看到其他人也遇到过它。无论如何,我可能已经能够制定出一个非常干净的解决方案。准备好后我会发布它作为答案。 @d4vidi 希望看到解决方案 我成功使用github.com/hadilq/LiveEvent库。 【参考方案1】:

我在 MutableLiveData 中使用 Google 示例中的这个 EventWraper 类

/**
 * 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;
    

在 ViewModel 中:

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

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

 public LiveData<Event<Boolean>> onSaveEvent() 
    return saveEvent;
 

在活动/片段中

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

【讨论】:

【参考方案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
        if (delegate != (other as FreshObserver<*>).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】:

拥有一些 RxJava 经验,我已经习惯于认为这种行为要求通常是 Observeable(在我们的例子中为 LiveData)所关心的问题。有许多operators,例如replay(),可以控制与用户实际发布的内容相比实际发布的内容(以及何时发布)。本质上,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 值)。

这基本上总结了它,但完整的文档,请转到我的gist。

用法

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

【讨论】:

【参考方案4】:

我创建了一个新的类来保存我的真实数据和一个“特殊 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()”方法来“设置/postValue()”我的“LiveDataItem”类型,而不是原来的“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));

然后我创建了一个普通的 Observer,它将接收所有“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”中删除那个 RealtimeNanos,然后将一个新的观察者附加到那个 LiveData。

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

【讨论】:

是的,我考虑为每个事件提供唯一 ID,好主意我会检查它,谢谢。【参考方案5】:

如果您按原样使用它们,我认为在开始观察时无法阻止 LiveData 接收最后一个值。您可以做的是扩展ViewModel class,使其仅在添加观察者时通知视图。

另一种选择是简单地忽略回调

    向 ViewModel 添加一个标志。

    private boolean isFirstTime = true;
    
    public boolean isFirstTime()  return isFirstTime; 
    
    public boolean onObserverAdded()  isFirstTime = false; `
    

    在回调中添加检查

    @Override
    public void onChanged(@Nullable final String newName) 
    boolean ignore = ((MyViewModel)ViewModelProviders.of(MyActivity.this).get(MyViewModel.class)).isFirstTime();
    if(ignore) return;
    
    // Update the UI
    
    

    添加观察者后最后调用onObserverAdded()

【讨论】:

【参考方案6】:

根据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))
        
    

fragment 内部实现observer 方法

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

【讨论】:

【参考方案7】:

我创建了一个 LiveData 对象FreshLiveData,它仅在调用setValuepostValue 后才向观察者发出onChange

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】:

没有理由使用 LiveData,因为它不是。如果您需要一个单独的行为(不保留先前值的东西),那么您应该使用不保留先前值的组件 - 而不是围绕它进行修改(“记住”它已经发出然后忘记发射等)

虽然没有其他正确的解决方案可用,所以我最终不得不自己写一个,所以我没有推荐的替代方案,我不得不推荐我为这个特定目的写的那个。

无论如何,你可以添加live-event库:

implementation 'com.github.Zhuinden:live-event:1.2.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()

【讨论】:

使用这个库超出了主要问题的目的/范围。作者要求为 LiveData 提供解决方案,而不是通用的解决方法/解决方案来达到他的成就。 LiveData 不是设计出来的,不适合这个。其他都是骗人的。 它怎么可能不是为这样一个简单的用例而设计的呢?例如:ViewModel 需要通知 View 发生错误,然后 View 显示 SnackBar。然后再次开始观察该观察者(活动重新启动),您会收到错误消息。对于这个用例,我还需要一些解决方法或技巧吗?对我来说最简单的解决方法是 RxJava。 @Nikola LiveData 像 BehaviorRelay 一样工作,它总是会发出最后一个发出的值。如果您需要 PublishRelay,那么 LiveData 将不是一个合适的解决方案。 “官方 Google 示例”使用 EventObserver + LiveData&lt;Event&lt;T&gt;&gt;,但实际上这只是 SingleLiveData 有更多代码,这已经像 BehaviorRelay.skip(1) 这很尴尬。 如果不引入一些 hack 或对抗框架,LiveData 无法解决此问题。 @EpicPandaForce 介绍的库很简单,经过良好测试,最重要的是,为我解决了手头的问题。【参考方案9】:

即使我也有同样的要求。我通过扩展 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);
    

【讨论】:

不起作用,因为处于后台的观察者在进入前台后不会获得更新的值。 @EgorNeliuba 你介意解释一下为什么这不起作用吗?我们要解决的问题不是阻止观察者返回前台后触发吗?【参考方案10】:

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

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】:

您可以使用this 文章中描述的 EventLiveData。它将解决您的问题,我在 2 个生产项目中使用了它。 它是 LiveData 扩展,就像 SingleLiveData 一样,但支持多个观察者。当观察者应该接收事件时,还允许自定义生命周期限制。例如,如果您不想在片段处于后台时接收事件。

EventLiveData 持有它永远观察的内部观察者,覆盖观察方法,将观察者保存到内部地图中,绕过原生 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;

【讨论】:

【参考方案12】:

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)
        
    

【讨论】:

如果setValue 从未被调用,那么您将泄漏任何留在unactivedObservers 中的观察者 我认为WeakReference 可以解决内存泄漏问题 可能,但为什么不解决该模式的问题,这样您就不必使用WeakReference

以上是关于LiveData 防止在开始观察时收到最后一个值的主要内容,如果未能解决你的问题,请参考以下文章

将项目添加到 LiveData 列表时通知观察者

在 xml 中设置/观察 livedata 的正确方法是啥?调用观察者方法失败

LiveData,是不是可以观察特定值

livedata数据倒灌与粘性事件

LiveData 在第一次回调后删除观察者

Android LiveData粘性,粘连,倒灌