LiveData粘性事件+LiveDataBus

LiveData粘性事件的问题2

之前在LiveData文章中已经分析过粘性事件的原因了,但是在实际使用中还是遇到了一些问题,

网上的UnstickyLiveData的写法通常是反射修改LiveData.ObserverWrapper.mLastVersion,

    @Override
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        super.observe(owner, observer);
        HookUtils.alignVersion(this, observer);
    }
public static void alignVersion(LiveData liveData, Observer observer) {
        Class<LiveData> liveDataClass = LiveData.class;
        try {
            //获取field private SafeIterableMap<Observer<T>, ObserverWrapper> mObservers
            Field mObservers = liveDataClass.getDeclaredField("mObservers");
            mObservers.setAccessible(true);

            //获取SafeIterableMap集合mObservers
            Object observers = mObservers.get(liveData);

            //获取SafeIterableMap的get(Object obj)方法
            Class<?> observersClass = observers.getClass();
            Method methodGet = observersClass.getDeclaredMethod("get", Object.class);
            methodGet.setAccessible(true);

            //获取到observer在集合中对应的ObserverWrapper对象
            Object objectWrapperEntry = methodGet.invoke(observers, observer);
            Object objectWrapper = null;
            if (objectWrapperEntry instanceof Map.Entry) {
                objectWrapper = ((Map.Entry) objectWrapperEntry).getValue();
            }
            if (objectWrapper == null) {
                throw new NullPointerException("ObserverWrapper can not be null");
            }

            //获取ObserverWrapper的Class对象  LifecycleBoundObserver extends ObserverWrapper
            Class<?> wrapperClass = objectWrapper.getClass().getSuperclass();

            //获取ObserverWrapper的field mLastVersion
            Field mLastVersion = wrapperClass.getDeclaredField("mLastVersion");
            mLastVersion.setAccessible(true);

            //把当前ListData的mVersion赋值给 ObserverWrapper的field mLastVersion
            mLastVersion.set(objectWrapper, liveData.getVersion());
        } catch (Exception e) {
            if (BuildConfig.DEBUG) {
                throw new RuntimeException(e);
            } else {
                e.printStackTrace();
            }
        }
    }

但是有个问题,如果在生命周期当前是:

owner.getLifecycle().getCurrentState().isAtLeast(STARTED)

那么里边会立马调用observer.onChange,这显然是有问题的,正确的做法应该是我下边的代码

    @Override
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");

        if (getVersion() > LiveData.START_VERSION) {//有新值,会调用onChanged
            if (owner.getLifecycle().getCurrentState().isAtLeast(STARTED)) {//此时super.observe内会立马调用onChanged
                PreventStickyEventObserverWrapper<? super T> myObserverWrapper = myObserverWrapperMap.get(observer);
                if (myObserverWrapper == null) {
                    myObserverWrapper = new PreventStickyEventObserverWrapper<>(observer);
                    myObserverWrapper.preventStickyEvent = true;
                    myObserverWrapperMap.put(observer, myObserverWrapper);
                    super.observe(owner, myObserverWrapper);
                }

            } else {
                super.observe(owner, observer);
                HookUtils.alignVersion(this, observer);
            }
        } else {
            super.observe(owner, observer);
        }
    }
class PreventStickyEventObserverWrapper<T> implements Observer<T> {

    @NonNull
    final Observer<T> observer;
    boolean preventStickyEvent = false;

    PreventStickyEventObserverWrapper(@NonNull Observer<T> observer) {
        this.observer = observer;
    }

    @Override
    public void onChanged(@Nullable T t) {
        if (preventStickyEvent) {
            preventStickyEvent = false;
            return;
        }
        observer.onChanged(t);
    }
}

这样就覆盖了各种情况。

LiveDataBus

事件总线是一种解耦的编程方式,特别是在页面深度特别深,需要通知之前的某个页面状态时非常有用,

主流的主要是EventBus,RxBus,但这些都有个问题就是生命周期感知的问题,

而LiveData之所以好,就是因为只在页面真正显示的时候才去通知观察者,所以仿照着前者写了个LiveDataBus,实现起来也很简单,看起来也很方便,没有其他的杂七杂八的逻辑。

github:https://github.com/wz147258/LiveDataBus

原文地址:https://www.cnblogs.com/muouren/p/13965452.html