LiveData升級版

前言

系統的Livedata由於內部使用ObserverWrapper封裝Observer,通過粘性效果實現通知,有些時候不需要粘性通知,需要在訂閱之後再觀察事件,通過反射修改如下:

public class BusMutableLiveData<T> extends MutableLiveData<T> {

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

    private void hook(Observer<? super T> 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(this);
            Class<?> observersClass = observers.getClass();
            //獲取SafeIterableMap的get(Object obj)方法
            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);
            //獲取liveData的field mVersion
            Field mVersion = liveDataClass.getDeclaredField("mVersion");
            mVersion.setAccessible(true);
            Object mV = mVersion.get(this);
            //把當前ListData的mVersion賦值給 ObserverWrapper的field mLastVersion
            mLastVersion.set(objectWrapper, mV);

            mObservers.setAccessible(false);
            methodGet.setAccessible(false);
            mLastVersion.setAccessible(false);
            mVersion.setAccessible(false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

封裝

上面試Livedata的封裝,平時使用的情況下簡化過程,封裝工具類如下:

public class LiveDataBus<T> {

    private final Map<String, BusMutableLiveData<T>> mBus;

    private LiveDataBus() {
        mBus = new ArrayMap<>();
    }

    private static abstract class SingleHolder {
        private static final LiveDataBus DATA_BUS = new LiveDataBus();
    }

    public static LiveDataBus get() {
        return SingleHolder.DATA_BUS;
    }


    /**
     * 訂閱事件
     *
     * @param event
     */
    public void subscribe(T event) {
        if (null == event) {
            throw new IllegalArgumentException("Subscribed events must be not null!");
        }

        String eventName = event.getClass().getName();
        if (!mBus.containsKey(eventName)) {
            mBus.put(eventName, new BusMutableLiveData<>());
        }

        BusMutableLiveData<T> liveData = mBus.get(eventName);
        if (null != liveData) {
            liveData.setValue(event);
        }
    }

    /**
     * 觀察事件
     *
     * @param eventType
     * @return
     */
    public T observable(Class<T> eventType) {
        String eventName = eventType.getName();
        if (TextUtils.isEmpty(eventName)) {
            throw new IllegalArgumentException("Observered events must be not null!");
        }
        return mBus.get(eventName).getValue();
    }

    /**
     * 觀察事件
     *
     * @param eventType
     * @return
     */
    public LiveData postObservable(Class<T> eventType) {
        String eventName = eventType.getName();
        if (TextUtils.isEmpty(eventName)) {
            throw new IllegalArgumentException("Observered events must be not null!");
        }
        BusMutableLiveData<T> tBusMutableLiveData = mBus.get(eventName);
        if(tBusMutableLiveData==null) {
            throw new IllegalArgumentException("The event you observe has not been subscribed!");
        }
        return mBus.get(eventName);
    }

}

第二種

public class LifecycleBus<T> {

    private MutableLiveData<T> liveData;
    public final static boolean MODE_SYSTEM = false;

    private LifecycleBus() {
    }

    private static abstract class SingleHolder {
        private static final LifecycleBus DATA_BUS = new LifecycleBus();
    }

    public static LifecycleBus get() {
        return LifecycleBus.SingleHolder.DATA_BUS;
    }

    /**
     * 訂閱事件
     *
     * @param event
     */
    protected void subscribe(T event) {
        subscribe(MODE_SYSTEM,event);
    }

    /**
     * 訂閱事件
     *
     * @param event
     */
    protected void subscribe(boolean useSystem,T event) {
        if (null == event) {
            throw new IllegalArgumentException("Subscribed events must be not null!");
        }
        liveData = useSystem ? new MutableLiveData() : new LifecycleLiveData();
        liveData.setValue(event);
    }

    /**
     * 觀察事件
     *
     * @param activity
     * @param observer
     */
    public void observe(@NonNull AppCompatActivity activity, @NonNull Observer<? super T> observer) {
        if (liveData == null) {
            throw new IllegalArgumentException("The event you observe has not been subscribed!");
        }
        if (liveData instanceof LifecycleLiveData) {
            LifecycleLiveData lifecycleLiveData = (LifecycleLiveData) liveData;
            lifecycleLiveData.observe(activity, observer);
        } else {
            liveData.observe(activity, observer);
        }
    }

    /**
     * 觀察事件
     *
     * @param fragment
     * @param observer
     */
    public void observe(@NonNull Fragment fragment, @NonNull Observer<? super T> observer) {
        if (liveData == null) {
            throw new IllegalArgumentException("The event you observe has not been subscribed!");
        }
        if (liveData instanceof LifecycleLiveData) {
            LifecycleLiveData lifecycleLiveData = (LifecycleLiveData) liveData;
            lifecycleLiveData.observe(fragment, observer);
        } else {
            liveData.observe(fragment, observer);
        }
    }


    /**
     * 內部類繼承
     * MutableLiveData
     *
     * @param <T>
     */
    public class LifecycleLiveData<T> extends MutableLiveData<T> {

        private final HashMap<Integer, Boolean> observers = new HashMap<>();

        public void observe(@NonNull AppCompatActivity activity, @NonNull Observer<? super T> observer) {
            LifecycleOwner owner = activity;
            Integer storeId = System.identityHashCode(activity.getViewModelStore());
            observe(storeId, owner, observer);
        }

        public void observe(@NonNull Fragment fragment, @NonNull Observer<? super T> observer) {
            LifecycleOwner owner = fragment.getViewLifecycleOwner();
            Integer storeId = System.identityHashCode(fragment.getViewModelStore());
            observe(storeId, owner, observer);
        }

        private void observe(@NonNull Integer storeId, @NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
            if (observers.get(storeId) == null) {
                observers.put(storeId, true);
            }
            super.observe(owner, t -> {
                if (!observers.get(storeId)) {
                    observers.put(storeId, true);
                }
                if (t != null) {
                    observer.onChanged(t);
                }
            });
        }

        /**
         * 禁用此方法
         *
         * @param observer
         */
        @Override
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        }

        /**
         * 禁用此方法
         *
         * @param observer
         */
        @Override
        public void observeForever(@NonNull Observer<? super T> observer) {
        }

        @Override
        public void setValue(T value) {
            if (value != null) {
                for (Map.Entry<Integer, Boolean> entry : observers.entrySet()) {
                    entry.setValue(false);
                }
                super.setValue(value);
            }
        }

        /**
         * 清理
         */
        public void clear() {
            super.setValue(null);
        }
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章