使用LiveData实现事件总线

107 阅读2分钟

流程

创建StickyLiveData,重写setValue、postValue,使用int类型的mVersion保存被设置值的次数

创建WrapperObserver,重写onChanged,判断事件是否重发,解决普通事件和粘性事件的问题

ConcurrentHashMap存储EventName,和StickyLiveData

代码

package com.mooc.libcommon.extention;


import android.app.Activity;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleEventObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;

import java.util.concurrent.ConcurrentHashMap;

public class LiveDataBus {

    private static class Lazy {
        static LiveDataBus sLiveDataBus = new LiveDataBus();
    }

    public static LiveDataBus get() {
        return Lazy.sLiveDataBus;
    }

    /**
     * 每次创建一个LiveData,就把它和它的eventName保存至hashMap中
     * @param eventName
     * @return
     */
    private static ConcurrentHashMap<String, StickyLiveData> mHashMap = new ConcurrentHashMap<>();
    public StickyLiveData with(String eventName) {
        StickyLiveData liveData = mHashMap.get(eventName);
        if (liveData == null) {
            liveData = new StickyLiveData(eventName);
            mHashMap.put(eventName, liveData);
        }
        return liveData;
    }

    /**
     * LiveData
     * 1:初始化,需要一个EventName
     * 2:用一个mVersion来标记setValue和postValue的次数
     * 3:每次当Observer的Lifecycle被销毁的时候,先把stickyLiveData移除
     * @param <T>
     */
    public static class StickyLiveData<T> extends LiveData<T> {
        private String mEventName;
        private T mStickyData;
        private int mVersion = 0;

        public StickyLiveData(String eventName) {
            mEventName = eventName;
        }

        @Override
        public void setValue(T value) {
            mVersion++;
            super.setValue(value);
        }

        @Override
        public void postValue(T value) {
            mVersion++;
            super.postValue(value);
        }

        public void setStickyData(T stickyData) {
            this.mStickyData = stickyData;
            setValue(stickyData);
        }

        public void postStickyData(T stickyData) {
            this.mStickyData = stickyData;
            postValue(stickyData);
        }

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

        public void observerSticky(LifecycleOwner owner, Observer<? super T> observer, boolean sticky) {
            super.observe(owner, new WrapperObserver(this, observer, sticky));
            owner.getLifecycle().addObserver(new LifecycleEventObserver() {
                @Override
                public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
                    if (event == Lifecycle.Event.ON_DESTROY) {
                        mHashMap.remove(mEventName);
                    }
                }
            });
        }

        /**
         * Observer包装类
         * 1:mLastVersion标记已经发射几次数据了
         * 2:初始化的时候,和LiveData的version进行同步操作,过滤重复数据
         * @param <T>
         */
        private class WrapperObserver<T> implements Observer<T> {
            private StickyLiveData<T> mLiveData;
            private Observer<T> mObserver;
            private boolean mSticky;

            // 标记该liveData已经发射几次数据了 用以过滤老数据重复接收
            private int mLastVersion = 0;

            public WrapperObserver(StickyLiveData liveData, Observer<T> observer, boolean sticky) {

                mLiveData = liveData;
                mObserver = observer;
                mSticky = sticky;

                // 此处的版本为什么保持一致,就是为了过滤老数据
                mLastVersion = mLiveData.mVersion;
            }


            /**
             * observer.mLastVersion >= mLiveData.mVersion
             * 这种情况 只会出现在,我们先行创建一个liveData发射了一条数据。此时liveData的mversion=1.
             *
             * 而后注册一个observer进去。由于我们代理了传递进来的observer,进而包装成wrapperObserver,此时wrapperObserver的lastVersion 就会跟liveData的mversion 对齐。保持一样。把wrapperObserver注册到liveData中。
             *
             * 根据liveData的原理,一旦一个新的observer 注册进去,也是会尝试把数据派发给他的。这就是黏性事件(先发送,后接收)。
             *
             * 但此时wrapperObserver的lastVersion 已经和 liveData的version 一样了。由此来控制黏性事件的分发与否
             */
            @Override
            public void onChanged(T t) {

                if (mLastVersion >= mLiveData.mVersion) {
                    if (mSticky && mLiveData.mStickyData != null) {
                        mObserver.onChanged(mLiveData.mStickyData);
                    }
                    return;
                }

                mLastVersion = mLiveData.mVersion;
                mObserver.onChanged(t);
            }
        }
    }

    /**
     * Handler的方式
     */
    private static void handler() {
        Handler mHandler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(@NonNull Message msg) {
                super.handleMessage(msg);
            }
        };

        mHandler.sendMessage(new Message());
    }

    /**
     * LiveData正常事件
     * @param activity
     */
    private static void liveData(Activity activity) {
        MutableLiveData<String> mLiveData = new MutableLiveData<>();
        mLiveData.observe((LifecycleOwner) activity, new Observer() {
            @Override
            public void onChanged(Object o) {

            }
        });
        mLiveData.postValue("fage");
    }

    /**
     * 粘性事件 先发送,后监听
     * @param activity
     */
    private static void stickyLiveData(Activity activity) {
        MutableLiveData<String> mLiveData = new MutableLiveData<>();
        mLiveData.postValue("dage");
        mLiveData.observe((LifecycleOwner) activity, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                
            }
        });
    }
}
  • 数据同步
LiveDataBus.get()
        .with(InteractionPresenter.DATA_FROM_INTERACTION)
        .observe((LifecycleOwner) mContext, mFeedObserver);
        
private FeedObserver mFeedObserver;
private class FeedObserver implements Observer<Feed> {

    private Feed mFeed;

    @Override
    public void onChanged(Feed newOne) {
        if (mFeed.id != newOne.id) {
            return;
        }
        mFeed.author = newOne.author;
        mFeed.ugc = newOne.ugc;
        mFeed.notifyChange();
    }

    public void setFeed(Feed feed) {
        mFeed = feed;
    }
}