美文网首页JetPack
LiveDataBus 使用

LiveDataBus 使用

作者: 放肆滴微笑 | 来源:发表于2019-12-24 16:17 被阅读0次

    rxbus

    优点 效率高,无内存泄露、UI和实时数据保持一致
    缺点: 依赖包 2.2M 比较大

    EventBus

    优点 使用简单、UI和实时数据保持一致
    缺点: 混淆问题,无法感知生命周期 很难追踪到发布源

    LiveDataBus

    优点:
    UI和实时数据保持一致
    避免内存泄露,内部实现
    不会在产生由于Activity处于stop状态而引起崩溃
    不需要解决生命周期带来的问题
    实时数据刷新
    解决Configuration chanage问题
    使用系统api

    liveData 是一个数据持有类,持有数据并且这个数据能被观察者所监听到,而且他是和lifecycle绑定,具有声明周期感知,解决内存泄露和引用问题

    所有的框架,如果和声明周期相关,里面肯定有lifecycle

    lifecycle 是android 官方退出的官方架构之一,他是具有生命周期感知的,不单能够监听Activity和Fragment的生命周期,还能回调相应的方法,同时他能够实时的获取当前Activity和fragment的状态

    image.png

    LiveDataBus使用中有个缺点,在A页面发送消息,再进入B页面,这个时候B页面还能接受到消息,是个错误,
    因为从事件上来说,需要注册后,再发送,

    发送一个事件

    # MutableLiveData
    public class MutableLiveData<T> extends LiveData<T> {
        @Override
        public void postValue(T value) {
            super.postValue(value);  //调用父类
        }
    }
    
    # LiveData
    protected void postValue(T value) {
            boolean postTask;
            synchronized (mDataLock) {
                postTask = mPendingData == NOT_SET;
                mPendingData = value;
            }
            if (!postTask) {
                return;
            }
            // 发现是个线程
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
        }
    
    # LiveData
    // 找到线程方法
     private final Runnable mPostValueRunnable = new Runnable() {
            @Override
            public void run() {
                Object newValue;
                synchronized (mDataLock) {
                    newValue = mPendingData;
                    mPendingData = NOT_SET;
                }
                //noinspection unchecked
                setValue((T) newValue);   // 通过它来赋值
            }
        };
    
    @MainThread
        protected void setValue(T value) {
            assertMainThread("setValue");
            mVersion++;  // 发现mVersion ++ 也就是发送一个事件 增加
            mData = value;
            dispatchingValue(null);
        }
    

    通过源码也就明白 mVersion 和 mLastVersion 开始都是0,发送一个事件mVersion +1 ,

    下面,通过hook 来改变
    在LiveDataBus中,也就是通过onChanged方法来接收监听,我们可以在接收到事件后,拦截监听,
    通过代码发现 observer.mLastVersion >= mVersion 这块如果大于或等于就可以拦截,退出这个方法,从而让observer.mObserver.onChanged((T) mData);不能执行,起到拦截的作用

    private void considerNotify(ObserverWrapper observer) {
            if (!observer.mActive) {
                return;
            }
            if (!observer.shouldBeActive()) {
                observer.activeStateChanged(false);
                return;
            }
            if (observer.mLastVersion >= mVersion) {
                return;   // 可以在这里进行hook 让他们相等
            }
            observer.mLastVersion = mVersion;
            // 进行发送 onChanged 事件
            observer.mObserver.onChanged((T) mData);
        }
    

    mVersion 就是LiveData 的成员变量,可以直接获取到
    mLastVersion 是ObserverWrapper的成员变量
    发现considerNotify方法是通过for循环遍历mObservers,我们找到mObservers

    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 SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
                new SafeIterableMap<>();
    
    

    发现 SafeIterableMap 的value 又是 Entry

    # SafeIterableMap
    protected Entry<K, V> get(K k) {
            Entry<K, V> currentNode = mStart;
            while (currentNode != null) {
                if (currentNode.mKey.equals(k)) {
                    break;
                }
                currentNode = currentNode.mNext;
            }
            return currentNode;
        }
    

    所以我们需要先找到mObservers,再获取其中的Entry,就获得到ObserverWrapper,从而改变mLastVersion,需要注意得到的ObserverWrapper是子类LifecycleBoundObserver,需要获取父类

    下面是完整代码

    public class LiveDataBus {
        private static final String TAG = "LiveDataBus";
        private static LiveDataBus liveDataBus = new LiveDataBus();
        // 创建一个容器 装载所有的订阅者
        private Map<String, BusMutableLiveData<Object>> bus;
    
        private LiveDataBus() {
            bus = new HashMap<>();
        }
    
        public static LiveDataBus getInstance() {
            return liveDataBus;
        }
    
        public synchronized <T> BusMutableLiveData<T> with(String key, Class<T> type) {
            if (!bus.containsKey(key)) {
                bus.put(key, new BusMutableLiveData<Object>());
            }
            return (BusMutableLiveData<T>) bus.get(key);
        }
    
        public static class BusMutableLiveData<T> extends MutableLiveData<T> {
            @Override
            public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
                super.observe(owner, observer);
                try {
                    hook(observer);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
            private void hook(Observer observer) throws Exception {
                // 获取 LiveData 的类对象
                Class<LiveData> liveDataClass = LiveData.class;
                //  获取 mVersion 对象
                Field mVersionField = liveDataClass.getDeclaredField("mVersion");
                mVersionField.setAccessible(true);
                // 获取 mObservers 对象
                Field mObserversField = liveDataClass.getDeclaredField("mObservers");
                mObserversField.setAccessible(true);
    
                // 通过get 能获取到mObservers这个成员变量
                // SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers
                // 因为MutableLiveData 是 LiveData的子类,所以直接this 就能获取
                Object mObservers = mObserversField.get(this);
    
                // 获取map 的get方法 ,map 获取的value 是Object类型
                Method get = mObservers.getClass().getDeclaredMethod("get", Object.class);
                get.setAccessible(true);
    
                // 执行get, mObservers 里面就是 Observer 和 ObserverWrapper,所以直接传递observer
                Object invoke = get.invoke(mObservers, observer);
                Object observerWrapper = null;
    
                // 如果 执行结果不为空 并且也是Entry类型,说明结果对的
                if (invoke != null && invoke instanceof Map.Entry) {
                    observerWrapper = ((Map.Entry) invoke).getValue();
                }
    
                if (observerWrapper == null) {
                    throw new NullPointerException();
                }
    
                // 这个时候获取到mObservers 的value 再来改变mLastVersion 的值
                Class<?> observerWrapperClass = observerWrapper.getClass();
                Log.i(TAG, "observerWrapperClass: "+observerWrapperClass);
                // 发现获取的类类型 是 LifecycleBoundObserver,是 ObserverWrapper 子类,所以要 getSuperclass
                Field mLastVersion = observerWrapperClass.getSuperclass().getDeclaredField("mLastVersion");
                mLastVersion.setAccessible(true);
    
                // 得到 mVersionField 的值
                Object o = mVersionField.get(this);
                // 将mVersionField的值 付给 mLastVersion
                mLastVersion.set(observerWrapper, o);
            }
        }
    

    使用
    通过postValue发送事件,可以传递事件名,和事件类型,注意发送事件名对应的类型 要和接收的类型一致

    # 发送
    LiveDataBus.getInstance().with("wx", String.class).postValue("Two");
    
    # 接收
    LiveDataBus.getInstance().with("wx",String.class).observe(this, new Observer<String>() {
                @Override
                public void onChanged(String s) {
                    Log.i(TAG, "onChanged: "+s);
                }
            });
    

    相关文章

      网友评论

        本文标题:LiveDataBus 使用

        本文链接:https://www.haomeiwen.com/subject/puwxoctx.html