非粘性的LiveData

前言

liveData 数据更新是通过版本控制的,在每次setValue时version加1,

实现非粘性,

1、官网有推荐有SignLiveDdata,

2、网上也有反射更改版本的

这里介绍一个使用另一个,自定义版本,扩展生命周期监听

原理

1、版本

        新建类,继承liveDta,成员变量mValueVersion, 在setValue里面+1

public class OptionalMutableLiveData<T> extends MutableLiveData<T> {
    private static final int START_VERSION = -1;

    private int mValueVersion = START_VERSION;

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

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

liveDta源码中,版本与生命周期控制是使用了包装,和map, 那么为什么我们不能也使用这个尼??  开撸

先定义包装类,看看是不是有点像了::


public class OptionalMutableLiveData<T> extends MutableLiveData<T> {
    private static final int START_VERSION = -1;

    /**
     * 装observer
     */
    private ArrayMap<Observer<T>,LTObserverWrapper> mObserverContainer = new ArrayMap<>();

......
......
......

    private class LTObserverWrapper implements Observer<T> {
        Observer<T> observer;
        int mVersion;

        /**
         *
         * @param observer
         * @param isStick 是否粘性
         */
        public LTObserverWrapper(Observer<T> observer, boolean isStick) {
            this.observer = observer;
            if(!isStick){
                mVersion = mValueVersion;
            }
        }

        @Override
        public void onChanged(T t) {
            if (mVersion >= mValueVersion) {
                return;
            }
            mVersion = mValueVersion;
            observer.onChanged(t);
        }
    }

}

继续看看怎么包装:

package com.ltcode.livedatabus;

public class OptionalMutableLiveData<T> extends MutableLiveData<T> {
    private static final int START_VERSION = -1;

    /**
     * 装observer
     */
    private ArrayMap<Observer<T>,LTObserverWrapper> mObserverContainer = new ArrayMap<>();

    private int mValueVersion = START_VERSION;

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

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


    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer, boolean isStick) {
        if (isStick) {

        }
        super.observe(owner, observer);
    }

    @Override
    public void observeForever(@NonNull Observer<? super T> observer) {
        super.observeForever(observer);
    }

    /**
     * 自定义包装
     */
    private class LTObserverWrapper implements Observer<T> {
        Observer<? super T> mObserver;
        int mVersion;

        /**
         *
         * @param observer
         * @param isStick 是否粘性
         */
        public LTObserverWrapper(Observer<? super T> observer, boolean isStick) {
            this.mObserver = observer;
            if(!isStick){
                mVersion = mValueVersion;
            }
        }

        @Override
        public void onChanged(T t) {
            if (mVersion >= mValueVersion) {
                return;
            }
            mVersion = mValueVersion;
            mObserver.onChanged(t);
        }
        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }

        void detachObserver() {
        }
    }

    class LTLifecycleObserver extends LTObserverWrapper implements LifecycleEventObserver {
        @NonNull
        final LifecycleOwner mOwner;

        LTLifecycleObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer, boolean isStick) {
            super(observer, isStick);
            mOwner = owner;
        }

        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
        }

        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }

        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }

    /**
     * ObserverForever 支持生命周期,主要用与onDestory移除
     */
    class LTLifecycleObserverForever extends LTLifecycleObserver {

        LTLifecycleObserverForever(@NonNull LifecycleOwner owner, Observer<? super T> observer, boolean isStick) {
            super(owner, observer, isStick);
        }
    }

    class LTObserverForever extends LTObserverWrapper {

        public LTObserverForever(Observer<? super T> observer, boolean isStick) {
            super(observer, isStick);
        }
    }
}

包装起上面准备好了, 接下来就是看我们怎么注册observer了, 方法重载,入参添加参数哈

public void observe( boolean isStick, @NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        if (isStick) {
            super.observe(owner, observer);
        } else {
            if (owner.getLifecycle().getCurrentState() == DESTROYED) {
                // ignore
                return;
            }
            LTLifecycleObserver wrapper = new LTLifecycleObserver(owner, observer, false);
            mObserverContainer.put(observer, wrapper);
            owner.getLifecycle().addObserver(wrapper);
            super.observe(owner, wrapper);
        }
    }

    public void observeForever(boolean isStick, LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        if (owner == null) {
            if (isStick) {
                super.observeForever(observer);
            } else {
                LTObserverForever wrapper = new LTObserverForever(observer, false);
                LTObserverWrapper existing = mObserverContainer.put(observer, wrapper);
                super.observeForever(wrapper);
            }
        } else {
            if (owner.getLifecycle().getCurrentState() == DESTROYED) {
                return;
            }
            LTLifecycleObserverForever wrapper = new LTLifecycleObserverForever(owner, observer, isStick);
            mObserverContainer.put(observer, wrapper);
            owner.getLifecycle().addObserver(wrapper);
            super.observeForever(wrapper);
        }
    }

写到这里, 其实监听基本已经OK 了,也支持非粘性了, 但是发现还没有做remove,我们继续

 @Override
    public void removeObserver(@NonNull Observer<? super T> observer) {
        IapObserverWrapper observerWrapper = mObserversContainer.remove(observer);
        if (observerWrapper != null) {
            observerWrapper.detachObserver();
            super.removeObserver(observerWrapper);
        } else {
            super.removeObserver(observer);
        }
    }

    @Override
    public void removeObservers(@NonNull LifecycleOwner owner) {
        Iterator<Map.Entry<Observer<? super T>, IapObserverWrapper>> iterator = mObserversContainer.entrySet()
                .iterator();
        while (iterator.hasNext()) {
            Map.Entry<Observer<? super T>, IapObserverWrapper> wrapper = iterator.next();
            if (wrapper.getValue().isAttachedTo(owner)) {
                wrapper.getValue().detachObserver();
                iterator.remove();
            }
        }
        super.removeObservers(owner);
    }

完成,最后上一份完整代码

package com.ltcode.livedatabus;

public class OptionalMutableLiveData<T> extends MutableLiveData<T> {
    private static final int START_VERSION = -1;

    /**
     * 装observer
     */
    private ArrayMap<Observer<? super T>, LTObserverWrapper> mObserverContainer = new ArrayMap<>();

    private int mValueVersion = START_VERSION;

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

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

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

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

    public void observe(boolean isStick, @NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        if (isStick) {
            super.observe(owner, observer);
        } else {
            if (owner.getLifecycle().getCurrentState() == DESTROYED) {
                // ignore
                return;
            }
            LTLifecycleObserver wrapper = new LTLifecycleObserver(owner, observer, false);
            mObserverContainer.put(observer, wrapper);
            owner.getLifecycle().addObserver(wrapper);
            super.observe(owner, wrapper);
        }
    }

    @Override
    public void observeForever(@NonNull Observer<? super T> observer) {
        super.observeForever(observer);
    }

    public void observeForever(boolean isStick, @NonNull Observer<? super T> observer) {
        observeForever(isStick, null, observer);
    }

    public void observeForeverNoStick(@NonNull Observer<? super T> observer) {
        observeForever(false, null, observer);
    }

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

    public void observeForever(boolean isStick, LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        if (owner == null) {
            if (isStick) {
                super.observeForever(observer);
            } else {
                LTObserverForever wrapper = new LTObserverForever(observer, false);
                LTObserverWrapper existing = mObserverContainer.put(observer, wrapper);
                super.observeForever(wrapper);
            }
        } else {
            if (owner.getLifecycle().getCurrentState() == DESTROYED) {
                return;
            }
            LTLifecycleObserverForever wrapper = new LTLifecycleObserverForever(owner, observer, isStick);
            mObserverContainer.put(observer, wrapper);
            owner.getLifecycle().addObserver(wrapper);
            super.observeForever(wrapper);
        }
    }


    @Override
    public void removeObserver(@NonNull Observer<? super T> observer) {
        LTObserverWrapper wrapper = mObserverContainer.remove(observer);
        if (wrapper != null) {
            wrapper.detachObserver();
            super.removeObserver(wrapper);
            return;
        }

        if (observer instanceof OptionalMutableLiveData.LTObserverWrapper) {
            wrapper = (OptionalMutableLiveData.LTObserverWrapper) observer;
            wrapper.detachObserver();
        }

        super.removeObserver(observer);
    }

    @Override
    public void removeObservers(@NonNull LifecycleOwner owner) {
        for (Map.Entry<Observer<? super T>, LTObserverWrapper> entry : mObserverContainer.entrySet()) {
            if (entry.getValue().isAttachedTo(owner)) {
                removeObserver(entry.getKey());
            }
        }
        super.removeObservers(owner);
    }

    /**
     * 自定义包装
     */
    private class LTObserverWrapper implements Observer<T> {
        Observer<? super T> mObserver;
        int mVersion = START_VERSION;

        /**
         * @param observer
         * @param isStick  是否粘性
         */
        public LTObserverWrapper(Observer<? super T> observer, boolean isStick) {
            this.mObserver = observer;
            if (!isStick) {
                mVersion = mValueVersion;
            }
        }

        @Override
        public void onChanged(T t) {
            if (mVersion >= mValueVersion) {
                return;
            }
            mVersion = mValueVersion;
            mObserver.onChanged(t);
        }

        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }

        void detachObserver() {
        }
    }

    class LTLifecycleObserver extends LTObserverWrapper implements LifecycleEventObserver {
        @NonNull
        final LifecycleOwner mOwner;

        LTLifecycleObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer, boolean isStick) {
            super(observer, isStick);
            mOwner = owner;
        }

        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
        }

        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }

        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }

    /**
     * ObserverForever 支持生命周期,主要用与onDestory移除
     */
    class LTLifecycleObserverForever extends LTLifecycleObserver {

        LTLifecycleObserverForever(@NonNull LifecycleOwner owner, Observer<? super T> observer, boolean isStick) {
            super(owner, observer, isStick);
        }
    }

    class LTObserverForever extends LTObserverWrapper {

        public LTObserverForever(Observer<? super T> observer, boolean isStick) {
            super(observer, isStick);
        }
    }
}

处理LiveData粘性事件通常可以采用以下几种方法: #### 重写LiveData的方法(Hook方式) 为了使 `mLastVersion >= mVersion`,可以重写LiveData中的方法,这就需要用到Hook。通过反射机制修改LiveData内部的状态,从而避免粘性事件的发生。以下是一个简单的示例代码: ```kotlin import androidx.lifecycle.LiveData import androidx.lifecycle.Observer import java.lang.reflect.Field import java.lang.reflect.Method class NonStickyLiveData<T> : LiveData<T>() { override fun observe(owner: androidx.lifecycle.LifecycleOwner, observer: Observer<in T>) { super.observe(owner, observer) try { // 获取LiveData的mObservers字段 val observersField: Field = LiveData::class.java.getDeclaredField("mObservers") observersField.isAccessible = true val observers = observersField.get(this) // 获取SafeIterableMap的get方法 val methodGet: Method = observers.javaClass.getDeclaredMethod("get", Any::class.java) methodGet.isAccessible = true val entry = methodGet.invoke(observers, observer) // 获取ObserverWrapper的mLastVersion字段 if (entry != null) { val observerWrapperClass = entry.javaClass.superclass val lastVersionField: Field = observerWrapperClass!!.getDeclaredField("mLastVersion") lastVersionField.isAccessible = true // 获取LiveData的mVersion字段 val versionField: Field = LiveData::class.java.getDeclaredField("mVersion") versionField.isAccessible = true val version = versionField.get(this) // 设置mLastVersion等于mVersion lastVersionField.set(entry, version) } } catch (e: Exception) { e.printStackTrace() } } } ``` 使用时,将原来的 `LiveData` 替换为 `NonStickyLiveData`: ```kotlin val nonStickyLiveData = NonStickyLiveData<String>() nonStickyLiveData.observe(this, Observer { value -> // 处理数据 }) ``` #### 使用SingleLiveEvent `SingleLiveEvent` 是一种特殊的 `LiveData`,它只能发送一次事件,发送后会自动重置,从而避免粘性事件。以下是一个简单的 `SingleLiveEvent` 实现: ```kotlin import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.Observer import java.util.concurrent.atomic.AtomicBoolean class SingleLiveEvent<T> : MutableLiveData<T>() { private val mPending = AtomicBoolean(false) override fun observe(owner: androidx.lifecycle.LifecycleOwner, observer: Observer<in T>) { super.observe(owner, Observer { t -> if (mPending.compareAndSet(true, false)) { observer.onChanged(t) } }) } override fun setValue(t: T?) { mPending.set(true) super.setValue(t) } override fun postValue(value: T?) { mPending.set(true) super.postValue(value) } } ``` 使用时: ```kotlin val singleLiveEvent = SingleLiveEvent<String>() singleLiveEvent.observe(this, Observer { value -> // 处理数据 }) singleLiveEvent.value = "新数据" ``` #### 使用第三方库 除了手动实现,还可以使用一些第三方库来处理粘性事件,例如 `LiveEvent` 库,它提供了更方便的方式来处理 `LiveData` 的粘性问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值