Kotlin版 自定义的LiveDataBus

先上代码:

Kotlin 复制代码
object LiveDataBusKT {

    //    private val bus: MutableMap<String, BusMutableLiveData<Any>> by lazy { HashMap() }
    private val MAX_BUS_COUNT = 100 // 最大允许的 bus 对象数量
    private val bus: LruCache<String, BusMutableLiveData<Any>> = LruCache(MAX_BUS_COUNT)
    //暴露一个线程安全的,给外界注册,订阅者关系
    @Synchronized
    fun <T>with(key:String,type:Class<T>,isStick: Boolean =true):BusMutableLiveData<T>{
        var liveData = bus.get(key)
        if (liveData == null) {
            liveData = BusMutableLiveData(isStick)
            bus.put(key, liveData)
        }
//        if (!bus.containsKey(key)){
//            bus[key] = BusMutableLiveData(isStick)
//        }
        return bus[key] as BusMutableLiveData<T>
    }
    class BusMutableLiveData<T> private constructor() :MutableLiveData<T>(){
        var isStick  =false //开启,关闭 粘性

        //次构造
        constructor(isStick: Boolean):this(){
            this.isStick =isStick
        }
        //hook
        override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
            super.observe(owner, observer)
            if (!isStick){
                hook(observer =observer)
            }else{
            }

        }

        private fun <T> hook(observer: Observer<in T>) {
            // 获取mLastVersion
            val liveDataClass = LiveData::class.java

            // getDeclaredField是可以获取一个类的所有字段.
            // getField只能获取类的public 字段.
            val mObserversField = liveDataClass.getDeclaredField("mObservers")
            mObserversField.isAccessible = true //private 修饰也可以访问
            val mObserversObject = mObserversField.get(this)

            // 获取 private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers = new SafeIterableMap<>();
            val mObserversClass = mObserversObject.javaClass

            // 获取 mObservers 的 get方法   protected Entry<K, V> get(K k){}
            val get = mObserversClass.getDeclaredMethod("get", Any::class.java)
            get.isAccessible = true

            // 执行get方法
            val invoke = get.invoke(mObserversObject, observer)

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

            if (observerWrapper == null) {
                throw NullPointerException("observerWrapper is null")
            }

            // 得到observerWrapper的类对象
            val superclass = observerWrapper.javaClass.superclass
            val mLastVersionField = superclass.getDeclaredField("mLastVersion")
            mLastVersionField.isAccessible = true

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

            // 版本对齐
            val versionValue = mVersionField.get(this)
            mLastVersionField.set(observerWrapper, versionValue)
        }

    }
}

为了开启,关闭粘性事件,使用了 isStick 控制。

通过继承 MutableLiveData,在observe的时候hook 获取 mLastVersion 和mVersion,进行版本对齐

相关推荐
_李小白1 分钟前
【Android UI开发】Android VideoView 使用介绍(一)
android·ui
Mr数据杨36 分钟前
【Codex】用学生支持周报模块跟踪个性化支持进展
android·java·javascript·django·codex·项目开发
名剑走天下43 分钟前
Android 面试题大全
android·kotlin
mmsx1 小时前
osmdroid 自定义地图视图:继承 MapView 的正确姿势与生命周期管理
android·osmdroid
ii_best2 小时前
移动开发工具按键精灵安卓版 OcrEx 识别总是漏字错字?改这一个参数,精度直接翻倍
android·ai编程·按键精灵
chjif3 小时前
Android 设备管控开发实战:自定义 Launcher 如何只显示指定 App?
android·kotlin
Dovis(誓平步青云)4 小时前
模拟器横评:电脑上看小说、追短剧用什么模拟器?MuMu、雷电、腾讯手游助手实测
android·java·服务器·前端·javascript·电脑
非凡ghost4 小时前
用 Kotlin 和 Jetpack Compose 重写的安卓视频播放器,原生体验有多流畅?
android·java·kotlin·音视频·软件需求
峥嵘life4 小时前
Android16 系统 APEX 模块调试总结
android·大数据·开发语言