zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    hadoop基础
    数据库基础知识
    sqoop基础
    大数据之常用linux常用命令
    zooKeeper基础
    impala基础
    Hbase基础
    Commitlint 提交规范类型
    理解JS闭包
    JS函数作用域及作用域链理解
  • 原文地址:https://www.cnblogs.com/muouren/p/13965452.html
Copyright © 2011-2022 走看看