美文网首页Android Jetpack
Jetpack系列-LiveData二次封装,去除粘性数据

Jetpack系列-LiveData二次封装,去除粘性数据

作者: 木水Code | 来源:发表于2022-05-11 10:32 被阅读0次

LiveData默认带有粘性数据特征,但是很多情况下并不需要粘性数据,这时候可以通过反射去修改mLastVersion和mVersion的值,使他们相等,就可以去掉粘性数据。

封装一个单例NoStickLiveData。

object NoStickLiveData {

    private val map: MutableMap<String, NoStickMutableLiveData<Any>> by lazy { HashMap() }

    @Synchronized
    fun <T> with(key: String, isStick: Boolean = false): NoStickMutableLiveData<T> {
        if (!map.containsKey(key)) {
            map[key] = NoStickMutableLiveData(isStick)
        }
        return map[key] as NoStickMutableLiveData<T>
    }

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

        private var isStick: Boolean = false

        constructor(isStick: Boolean) : this() {
            this.isStick = isStick
        }

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

            if (!isStick) {
                solveStick(observer)
            }
        }

        /**
         * 使用反射将mLastVersion的值改为和mVersion相同,就可以解决粘性数据问题
         */
        private fun solveStick(observer: Observer<in T>) {
            val liveDataClass = LiveData::class.java

            //先拿到observer.mLastVersion,mLastVersion在ObserverWrapper中,ObserverWrapper又存放在mObservers中

            //获取mObserversFiled
            val mObserversFiled = liveDataClass.getDeclaredField("mObservers")
            mObserversFiled.isAccessible = true

            //获取map值,this就是LiveData
            val mObserversMap: Any = mObserversFiled.get(this)

            //拿到mObserversMap的class
            val mObserversMapClass = mObserversMap.javaClass

            //获取map的get方法
            val mObserversMapGet = mObserversMapClass.getDeclaredMethod("get", Any::class.java)
            mObserversMapGet.isAccessible = true

            //执行map的get方法,获取ObserverWrapper
            var observerWrapper: Any? = null
            val invokeEntry = mObserversMapGet.invoke(mObserversMap, observer)
            if (invokeEntry != null && invokeEntry is Map.Entry<*, *>) {
                observerWrapper = invokeEntry.value
            } else {
                throw Exception("observerWrapper error")
            }

            //获取ObserverWrapper中的mLastVersion
            //由于这里获取到的的是ObserverWrapper的子类LifecycleBoundObserver或AlwaysActiveObserver
            //所以需要先用superclass获取超类
            val observerWrapperSuperClass = observerWrapper?.javaClass?.superclass
            val mLastVersionFiled = observerWrapperSuperClass?.getDeclaredField("mLastVersion")
            mLastVersionFiled?.isAccessible = true

            //获取mVersion
            val mVersionFiled = liveDataClass.getDeclaredField("mVersion")
            mVersionFiled.isAccessible = true
            //拿到mVersion的值
            val mVersion = mVersionFiled.get(this)

            //将mLastVersion的值设置成跟mVersion相同
            mLastVersionFiled?.set(observerWrapper, mVersion)
        }
    }
}

使用,在NoStick1Activity先修改数据,然后再跳转到NoStick2Activity,可以看到NoStickLiveData.with传true,会正常有粘性数据,传false,就没有粘性数据。

class NoStick1Activity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_no_stick1)

        //参数isStick为tru,表示有粘性
        NoStickLiveData.with<String>("stick_data", true).value = "message----stick_data"
        //参数isStick不传或者为false,表示没有粘性
        NoStickLiveData.with<String>("noStick_data").value = "message----noStick_data"

        findViewById<Button>(R.id.button).setOnClickListener {
            startActivity(Intent(this, NoStick2Activity::class.java))
        }
    }
}
class NoStick2Activity : AppCompatActivity() {

    private val TAG = "NoStick2Activity"

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

        NoStickLiveData.with<String>("stick_data", false).observe(this) {
            Log.d(TAG, "stick_data: $it")
        }
        NoStickLiveData.with<String>("noStick_data").observe(this) {
            Log.d(TAG, "noStick_data: $it")
        }
    }
}

相关文章

网友评论

    本文标题:Jetpack系列-LiveData二次封装,去除粘性数据

    本文链接:https://www.haomeiwen.com/subject/ouhlurtx.html