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

2023-08-16  本文已影响0人  喂_balabala

《Lifecycle原理、源码解析》
《LiveData简介及使用-什么是LiveData的粘性事件(数据倒灌)?》

    @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);
    }
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);
    }
}
    @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--;
    }
protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
private final Runnable mPostValueRunnable = new Runnable() {
        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            setValue((T) newValue);
        }
    };
@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);
}


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

为什么会有粘性事件?

原因:执行顺序变了
处理方案: 让第一次setValue不起效即可
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();
            }
        }
    }
}

上一篇下一篇

猜你喜欢

热点阅读