Jetpack 中的 LiveData 粘性事件

什么叫粘性事件

LiveData使用篇Jetpack 中的 LiveData - 使用篇_简单不一定不好的博客-优快云博客后再进一步了解LiveData。观察者和被观察者,正常情况下观察者先注册,被观察者再发送观察事件;所以粘性事件可以理解为观察者模式的升级,可以让观察者与被观察者之间更加的粘合,即是可先发送观察者事件,再注册观察者。

粘性事件测试

ViscosityActivity
class ViscosityActivity : AppCompatActivity() {

    private var textView: TextView? = null
    private var num = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_viscosity)

        textView = findViewById(R.id.textView)


        MyLiveData.data.observe(this, { msg ->
            Log.d("liveData", "界面显示:$msg")
            textView?.text = msg
        })
        MyLiveData.data.value = "Default"
        findViewById<Button>(R.id.bt).setOnClickListener {
            MyLiveData.data.value = "Default:${++num}"
        }
        findViewById<Button>(R.id.bt2).setOnClickListener {
            startActivity(Intent(this,ViscosityActivity2::class.java))
        }

    }
}
ViscosityActivity2
class ViscosityActivity2 : AppCompatActivity() {

    private var textView: TextView? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_viscosity)

        textView = findViewById(R.id.textView)


        MyLiveData.data.observe(this, { msg ->
            Log.d("liveData2", "界面显示:$msg")
            textView?.text = msg
        })
    }
}

运行结果:ViscosityActivity 变化的结果 ViscosityActivity2 也显示一样

 粘性事件分析

当被观察者 setValue 时候 mVersion 累加,

@MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }

观察者包装类也封装一个 mLastVersion 初始化 -1 值

private abstract class ObserverWrapper {
        final Observer<? super T> mObserver;
        boolean mActive;
        int mLastVersion = START_VERSION;

        ObserverWrapper(Observer<? super T> observer) {
            mObserver = observer;
        }

        abstract boolean shouldBeActive();

        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }

        void detachObserver() {
        }

        void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive;
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            if (wasInactive && mActive) {
                onActive();
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }

当 setValue 时候,对比被观察者 和观察者 version是否一致后再 onChanged 通知观察者

private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {
            return;
        }
        // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
        //
        // we still first check observer.active to keep it as the entrance for events. So even if
        // the observer moved to an active state, if we've not received that event, we better not
        // notify for a more predictable notification order.
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        observer.mObserver.onChanged((T) mData);
    }

如何剔除粘性事件

object OkLiveDataBus {

    //存放订阅者
    private val bus: MutableMap<String, BusMutableLiveData<Any>> by lazy { HashMap() }

    @Synchronized
    fun <T> with(key: String, type: Class<T>, isStick: Boolean = true): BusMutableLiveData<T> {
        if (!bus.containsKey(key)) {
            bus[key] = BusMutableLiveData(isStick)
        }
        return bus[key] as BusMutableLiveData<T>
    }

    class BusMutableLiveData<T> private constructor() : MutableLiveData<T>() {

        var isStick: Boolean = false//开启, 关闭黏性

        //次构造
        constructor(isStick: Boolean) : this() {

        }

        override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
            super.observe(owner, observer)
            if (!isStick) {
                hook(observer = observer)
                Log.d("jetpack", "Kotlin版本的 不启用黏性")
            } else {
                Log.d("jetpack", "Kotlin版本的启用黏性")
            }
        }
    }

    private fun <T> hook(observer: Observer<in T>) {
        //获取LiveDat 的类中的mObservers对象
        val liveDataClass = LiveData::class.java

        //SafeIterableMap <Observer<? super T>, ObserverWrapper>
        val mObservers: Field = LiveData::class.java.getDeclaredField("mObservers")
        mObservers.isAccessible = true//私有修饰也可以访问

        //获取到这个成员变量的对象 Any == Object
        val mObserversValue = mObservers.get(this)

        //得到map 对象的 class对象
        val mObserversClass: Class<*> = mObserversValue.javaClass

        //获取到mObservers 对象的get方法
        val get: Method = mObserversClass.getDeclaredMethod("get", Any::class.java)
        get.isAccessible = true

        //执行get方法
        val invokeEntry: Any = get.invoke(mObserversValue, observer)

        //取到entry中 的value
        var observerWrapper: Any? = null
        if (invokeEntry != null && invokeEntry is Map.Entry<*, *>) {
            observerWrapper = invokeEntry.value
        }
        if (observerWrapper == null) {
            throw NullPointerException("observerWrapper is null")
        }

        //得到observerWrapper的类对象
        val supperClass: Class<*> = observerWrapper.javaClass.superclass
        val mLastVersion: Field = supperClass.getDeclaredField("mLastVersion")
        mLastVersion.isAccessible = true

        //得到mVersion
        val mVersion: Field = liveDataClass.getDeclaredField("mVersion")
        mVersion.isAccessible = true

        val mVersionValue = mVersion.get(this)
        mLastVersion.set(observerWrapper, mVersionValue)
    }
}

参考:

为什么Google要将LiveData设计成粘性的 - 掘金

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值