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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM