LiveData原理、源码分析-粘性事件(数据倒灌)分析及解决

《Lifecycle原理、源码解析》

《LiveData简介及使用-什么是LiveData的粘性事件(数据倒灌)?》

  • 查看LiveData的observe可知是如何绑定的
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        ObserverWrapper existing = mObservers.putIfAbsent(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);
    }
  • owner就是activity。这个函数就可看出已经绑定上了
  • 里面有个关键函数是LifecycleBoundObserver的创建
  • LifecycleBoundObserver是ObserverWrapper的子类
  • ObserverWrapper有个activeStateChanged函数很关键,下面还会提到
  • 记住activeStateChanged里也调用了dispatchingValue
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 = LiveData.this.mActiveCount == 0;
    LiveData.this.mActiveCount += mActive ? 1 : -1;
    if (wasInactive && mActive) {
        onActive();
    }
    if (LiveData.this.mActiveCount == 0 && !mActive) {
        onInactive();
    }
    if (mActive) {
        dispatchingValue(this);
    }
}
  • 再看owner.getLifecycle().addObserver(wrapper)
  • 实现是在LifecycleRegister里的addObserver函数
  • 里面调用了calculateTargetState,去计算当前生命周期的状态,状态更新了就会触发ObserverWrapper里面的activeStateChanged
  • 这样就又执行了activeStateChanged里面的dispatchingValue函数
  • 这里也是LiveData粘性事件的根源
    @Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

        if (previous != null) {
            return;
        }
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            // it is null we should be destroyed. Fallback quickly
            return;
        }

        boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
        State targetState = calculateTargetState(observer);
        mAddingObserverCounter++;
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            popParentState();
            // mState / subling may have been changed recalculate
            targetState = calculateTargetState(observer);
        }

        if (!isReentrance) {
            // we do sync only on the top level.
            sync();
        }
        mAddingObserverCounter--;
    }
  • 再看LiveData类中的postValue函数
protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
  • postToMainThread看名字也可知post最终是传到主线程调用
private final Runnable mPostValueRunnable = new Runnable() {
        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            setValue((T) newValue);
        }
    };
  • 再看mPostValueRunnable可知postValue最终也是调用的setValue
  • 关键函数在setValue -> dispatchingValue -> considerNotify
  • 由此代码顺序可看出最终就在considerNotify里调用onChanged来完成通知的
@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}

...
...

void dispatchingValue(@Nullable ObserverWrapper initiator) {
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {
            considerNotify(initiator);
            initiator = null;
        } else {
            for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

...
...

private void considerNotify(ObserverWrapper observer) {
    if (!observer.mActive) {
        return;
    }
    // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
    //
    // we still first check observer.active to keep it as the entrance for events. So even if
    // the observer moved to an active state, if we've not received that event, we better not
    // notify for a more predictable notification order.
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    observer.mObserver.onChanged((T) mData);
}

  • setValue里面有一个mVersion,每次数据变化就加加
  • considerNotify先判断当前activity是否可见,然后再判断是否还没来得及更新activity的可见状态。此知识点需先了解lifecycle
  • considerNotify里面会判断mLastVersion和mVersion的值。版本不一致才会往下走,通知最新的数据变化

static final int START_VERSION = -1;

public LiveData(T value) {
    mData = value;
    mVersion = START_VERSION + 1;
}

/**
 * Creates a LiveData with no value assigned to it.
 */
public LiveData() {
    mData = NOT_SET;
    mVersion = START_VERSION;
}
  • 查看LiveData的构造函数可知,一般我们使用的是空参构造,所以mVersion的初始值是-1
为什么会有粘性事件?
原因:执行顺序变了
  • 原来的执行顺序new LiveData–>绑定observer–>setValue执行onChanged
  • 而我们的BUS在用时可能出现 new LiveData–>setValue执行onChanged–>绑定observer
  • 通过setValue函数可知只要调用一次,mVersion就加一,activity还没创建,也就是还没绑定observer的时候也加一了。
  • setValue会调用dispatchingValue(null),参数是null,会走里面的for循环,此时是没什么影响,因为mObservers找不到还没绑定的activity。
  • 但是假如setValue发送了10次,此时mVersion就已经是10了
  • 然后activity再创建,再绑定observer的时候,查看LiveData的observe函数,再查看里面的关键函数LifecycleBoundObserver的创建
  • LifecycleBoundObserver是ObserverWrapper的子类
  • ObserverWrapper有个activeStateChanged函数
  • activeStateChanged里也调用了dispatchingValue
  • 因为在绑定的时候就会监听生命周期变化,状态变了就触发状态更新
  • 又会执行considerNotify,此时mVersion已经是10了,但是mLastVersion还是-1,所以就往下走,就收到了旧数据的通知
处理方案: 让第一次setValue不起效即可
  • 自定义MutableLiveData,重写observe,反射修改mLastVersion的值,让它跟mVersion相等
package com.example.livedatabus;


import android.arch.lifecycle.LifecycleOwner;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.Observer;
import android.support.annotation.NonNull;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;


public class LiveDataBus {

    private static volatile LiveDataBus liveDataBus = null;
    private Map<String, BalaLiveDataBus<Object>> map = null;

    private LiveDataBus() {
        map = new HashMap<>();
    }

    public static LiveDataBus getLiveDataBus() {
        if (liveDataBus == null) liveDataBus = new LiveDataBus();
        return liveDataBus;
    }

    public void removeData(String... keys){
        for (String key : keys) {
            map.remove(key);
        }
    }

    public synchronized <T> BalaLiveDataBus<T> with(String str, Class<T> objectClass) {

        if (!map.containsKey(str)) {
            map.put(str, new BalaLiveDataBus<Object>());
        }
        return (BalaLiveDataBus<T>) map.get(str);
    }

    /**
     * 为了不执行 MutableLiveData 中Observer的onChange方法  观察源码如下:
     * <p>
     * if (!observer.mActive) {
     * return;
     * }
     * // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
     * //
     * // we still first check observer.active to keep it as the entrance for events. So even if
     * // the observer moved to an active state, if we've not received that event, we better not
     * // notify for a more predictable notification order.
     * if (!observer.shouldBeActive()) {
     * observer.activeStateChanged(false);
     * return;
     * }
     * if (observer.mLastVersion >= mVersion) {
     * return;
     * }
     * observer.mLastVersion = mVersion;
     * //noinspection unchecked
     * observer.mObserver.onChanged((T) mData);
     * <p>
     * 思路:让 observer.mLastVersion == mVersion (此修改不会改动到源码本来的逻辑)
     * <p>
     * 观察源码发现:
     * mVersion 是 LiveData的成员变量
     * observer.mLastVersion 的 observer 是 ObserverWrapper对象
     * ObserverWrapper 是 Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator中的value
     * iterator 相当于是 LiveData 中的成员变量 SafeIterableMap<Observer<T>, ObserverWrapper> mObservers
     *
     * @param <T>
     */
    public static class BalaLiveDataBus<T> extends MutableLiveData<T> {

        private boolean mIsViscidity = true;

        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer, boolean isViscidity) {
            mIsViscidity = isViscidity;
            observe(owner, observer);
        }

        @Override
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
            super.observe(owner, observer);
            if (mIsViscidity) return;
            try {
                Class<LiveData> liveDataClass = LiveData.class;
                //获取到mObservers对象
                Field mObserversField = liveDataClass.getDeclaredField("mObservers");
                mObserversField.setAccessible(true);
                //从当前的livedata对象中获取mObservers在当前成员变量中的值
                Object mObservers = mObserversField.get(this);
                //获取到mObservers的类型 SafeIterableMap
                Class<?> mObserversClass = mObservers.getClass();
                //获取到SafeIterableMap的get方法
                //get参数是一个泛型 但是又要传class对象  所以传object的
                Method get = mObserversClass.getDeclaredMethod("get", Object.class);
                get.setAccessible(true);
                //要执行mObservers的get方法  参数是observer
                //此时的对象就是 Entry<K, V>
                Object invokeEntry = get.invoke(mObservers, observer);
                Object observerWrapper = null;
                if (invokeEntry != null && invokeEntry instanceof Map.Entry) {
                    observerWrapper = ((Map.Entry) invokeEntry).getValue();
                }
                if (observerWrapper == null) {
                    throw new NullPointerException("observerWrapper==null");
                }
                /*
                 *为什么要获取父类对象?因为在LiveData的observe中new的是ObserverWrapper的子类
                 * LifecycleBoundObserver,但是要找的mLastVersion在ObserverWrapper中
                 */
                Class<?> superclassWrapper = observerWrapper.getClass().getSuperclass();
                Field mLastVersion = superclassWrapper.getDeclaredField("mLastVersion");
                mLastVersion.setAccessible(true);
                Field mVersion = liveDataClass.getDeclaredField("mVersion");
                mVersion.setAccessible(true);
                //从当前的livedata对象中获取mVersion的值
                Object o = mVersion.get(this);
                //mVersion的值给mLastVersion  mLastVersion是在observerWrapper里面的
                mLastVersion.set(observerWrapper, o);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值