深入理解AAC架構(gòu) - LiveDataBus 基于LiveData實(shí)現(xiàn)的事件總線

LiveData作為AAC架構(gòu)的關(guān)鍵模塊之一,具有優(yōu)秀的生命周期感知特性。
本身采用觀察者模式,由于其生命周期感知特性,可以用來實(shí)現(xiàn)事件總線。

本文主要內(nèi)容:

  • 基本思路:基本的實(shí)現(xiàn)思路
  • 粘性事件特性分析:LiveData觀察時(shí)推最新數(shù)據(jù)引發(fā)的問題
  • 解決思路:解決思路和引入粘性事件

本文主要采用反射對Version進(jìn)行管理,使用Class作為消息管理。
也可以使用其他實(shí)現(xiàn)方案,或在參考后自建方案:

本文源碼直接拷貝即可使用。
也可以前往GitHub倉庫查看下載:LiveDataBus (采用反射+包裝類的形式)


基本思路:

  • observe()
    即調(diào)用LiveData.observe(),基于LiveData的生命周期特性自動(dòng)管理觀察者。
  • observeForever()
    即調(diào)用LiveData.observeForever(),對無法提供LifecycleOwner的觀察者進(jìn)行支持。
  • removeObserver()
    即調(diào)用LiveData.removeObserver(),移除對應(yīng)觀察者。
  • postMessage()
    發(fā)布任意類型的消息,消息會(huì)通知所有關(guān)注此類型的觀察者。
object LiveDataBus {
    private val mBus: MutableMap<String, MutableLiveData<*>> = hashMapOf()

    fun <T : Any> observe(channelClass: Class<T>, owner: LifecycleOwner, observer: Observer<T>) {
        getChannel(channelClass).observe(owner, observer)
    }

    fun <T : Any> observeForever(channelClass: Class<T>, observer: Observer<T>) {
        getChannel(channelClass).observeForever(observer)
    }

    fun <T : Any> removeObserver(channelClass: Class<T>, observer: Observer<T>) {
        getChannel(channelClass).removeObserver(observer)
    }

    fun <T : Any> postMessage(message: T) {
        getChannel(message::class.java as Class<T>).postValue(message)
    }

    private fun <T : Any> getChannel(channelClass: Class<T>): MutableLiveData<T> {
        val channelName = channelClass.simpleName
        if (!mBus.containsKey(channelName)) {
            mBus[channelName] = MutableLiveData<T>()
        }
        return mBus[channelName] as MutableLiveData<T>
    }
}

使用方式:

// 定義信息
class Message

// 訂閱信息
LiveDataBus.observe(Message::class.java, mAnyLifecycleOwner, Observer { })
LiveDataBus.observeForever(Message::class.java, Observer { })

// 發(fā)布信息
LiveDataBus.postMessage(Message())

粘性事件問題

網(wǎng)上很多LiveDataBus的實(shí)現(xiàn)都有對該問題進(jìn)行分析,主要源自LiveData的實(shí)時(shí)通知觀察者特性,這個(gè)原來相當(dāng)優(yōu)秀的機(jī)制,在用來實(shí)現(xiàn)LiveDataBus的時(shí)候,反而會(huì)引發(fā)觀察時(shí)收到舊消息的問題。

解決方法并不復(fù)雜,通過自定義BusLiveData繼承MutableLiveData,并重寫observe()observeForever()

  • observe()。
    用于通過observe()加入的observer,通過反射,使ObserverWrapper維護(hù)的數(shù)據(jù)版本等于當(dāng)前LiveData數(shù)據(jù)版本。
    在觸發(fā)生命周期回調(diào)時(shí),由于數(shù)據(jù)版本相同,系統(tǒng)判斷為已通知,即不會(huì)觸發(fā)數(shù)據(jù)更新。
  • observeForever()
    使通過observeForever()新加入的observer,需要屏蔽所有通過observeForever()發(fā)起的onChanged()調(diào)用。
    通過把傳入的observer通過一個(gè)自定義的ObserverWrapper裝修類,在onChanged()判斷當(dāng)前調(diào)用棧是否有observeForever(),存在時(shí)則不觸發(fā)實(shí)際的observer.onChanged()。

最終方案

最后修改后的LiveDataBus

/**
 * LiveDataBus
 * 基于LiveData實(shí)現(xiàn)的事件總線
 */
object LiveDataBus {
    private val mBus by lazy { mutableMapOf<String, BusLiveData<*>>() }

    fun <T : Any> observe(channel: Class<T>, owner: LifecycleOwner, observer: Observer<T>) {
        getChannel(channel).observe(owner, observer)
    }

    fun <T : Any> observeSticky(channel: Class<T>, owner: LifecycleOwner, observer: Observer<T>) {
        getChannel(channel).observeStick(owner, observer)
    }

    fun <T : Any> observeForever(channel: Class<T>, observer: Observer<T>) {
        getChannel(channel).observeForever(observer)
    }

    fun <T : Any> observeStickyForever(channel: Class<T>, observer: Observer<T>) {
        getChannel(channel).observeStickyForever(observer)
    }

    fun <T : Any> removeObserver(channelClass: Class<T>, observer: Observer<T>) {
        getChannel(channelClass).removeObserver(observer)
    }

    fun <T : Any> postMessage(message: T) {
        getChannel(message::class.java as Class<T>).postValue(message)
    }

    private fun <T : Any> getChannel(channelClass: Class<T>): BusLiveData<T> {
        return mBus.getOrPut(channelClass.simpleName) {
            BusLiveData<T>()
        } as BusLiveData<T>
    }

    /**
     * 自定義的LiveData
     *
     * 用于通過`observe()`加入的`observer`
     * 通過反射,使`ObserverWrapper`維護(hù)的數(shù)據(jù)版本等于當(dāng)前`LiveData`數(shù)據(jù)版本。
     * 在觸發(fā)生命周期回調(diào)時(shí),由于數(shù)據(jù)版本相同,系統(tǒng)判斷為已通知,即不會(huì)觸發(fā)數(shù)據(jù)更新。
     *
     * 使通過`observeForever()`新加入的`observer`
     * 需要屏蔽所有通過`observeForever()`發(fā)起的`onChanged()`調(diào)用。
     * 通過把傳入的`observer`通過一個(gè)自定義的`ObserverWrapper`裝修類。
     * 在`onChanged()`判斷當(dāng)前調(diào)用棧是否有`observeForever()`,存在時(shí)則不觸發(fā)實(shí)際的`observer.onChanged()`。
     */
    private class BusLiveData<T> : MutableLiveData<T>() {

        // 反射緩存
        private companion object {
            private const val fieldObservers = "mObservers"
            private const val methodGet = "get"
            private const val fieldLastVersion = "mLastVersion"
            private const val fieldVersion = "mVersion"
            private val mCache = hashMapOf<String, Any>()
        }

        private val mRealMap = hashMapOf<Observer<*>, Observer<*>>()

        override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
            super.observe(owner, observer)
            setObserverVerToLiveDataVer(observer)
        }

        fun observeStick(owner: LifecycleOwner, observer: Observer<in T>) {
            super.observe(owner, observer)
        }

        override fun observeForever(observer: Observer<in T>) {
            super.observeForever(mRealMap.getOrPut(observer) {
                WrapperObserver(observer)
            } as Observer<in T>)
        }

        fun observeStickyForever(observer: Observer<in T>) {
            super.observeForever(observer)
        }

        override fun removeObserver(observer: Observer<in T>) {
            if (mRealMap.containsKey(observer)) {
                super.removeObserver(mRealMap.remove(observer) as Observer<T>)
            } else {
                super.removeObserver(observer)
            }
        }

        private fun setObserverVerToLiveDataVer(observer: Observer<in T>) {
            val liveDataClass = LiveData::class.java
            try {
                val mObserversField: Field = mCache.getOrPut(fieldObservers) {
                    val field = liveDataClass.getDeclaredField(fieldObservers)
                    field.isAccessible = true
                    field
                } as Field
                val mObservers = mObserversField[this]

                val getMethod = mCache.getOrPut(methodGet) {
                    val method = mObservers.javaClass.getDeclaredMethod(methodGet, Any::class.java)
                    method.isAccessible = true
                    method
                } as Method

                val boundObserverEntry = getMethod.invoke(mObservers, observer)
                var boundObserver: Any? = null
                if (boundObserverEntry is Map.Entry<*, *>) {
                    boundObserver = boundObserverEntry.value
                }
                if (boundObserver == null) {
                    throw NullPointerException("LifecycleBoundObserver cant be null")
                }

                val mLastVersionField = mCache.getOrPut(fieldLastVersion) {
                    val wrapperClass: Class<in Any> = boundObserver.javaClass.superclass
                            ?: throw NullPointerException("Cant access ObserverWrapper.class")
                    val field = wrapperClass.getDeclaredField(fieldLastVersion)
                    field.isAccessible = true
                    field
                } as Field

                val mVersionField = mCache.getOrPut(fieldVersion) {
                    val field = liveDataClass.getDeclaredField(fieldVersion)
                    field.isAccessible = true
                    field
                } as Field

                mLastVersionField.set(boundObserver, mVersionField[this])
            } catch (e: Exception) {
            }
        }
    }

    /**
     * Observer包裝類
     */
    private class WrapperObserver<T>(
            private val observer: Observer<T>
    ) : Observer<T> {

        private companion object {
            private const val clazz = "android.arch.lifecycle.LiveData"
            private const val func = "observeForever"
        }

        override fun onChanged(t: T) {
            if (!isCallOnObserve()) {
                observer.onChanged(t)
            }
        }

        private fun isCallOnObserve(): Boolean {
            for (element in Thread.currentThread().stackTrace) {
                if (clazz == element.className && func == element.methodName) {
                    return true
                }
            }
            return false
        }
    }
}

使用方式:

// 定義信息
class Message

// 訂閱信息
LiveDataBus.observe(Message::class.java, this, Observer { })
LiveDataBus.observeForever(Message::class.java, Observer { })

// 訂閱粘性信息
LiveDataBus.observeSticky(Message::class.java, this, Observer { })
LiveDataBus.observeStickyForever(Message::class.java, Observer { })

// 發(fā)布信息
LiveDataBus.postMessage(Message())
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容