在上一篇LiveData的原理分析(https://blog.csdn.net/xxwbwm/article/details/124395615?spm=1001.2014.3001.5501)中发现Google的源码是默认存在粘性数据的,原因:
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
//核心判断
if (observer.mLastVersion >= mVersion) {
return;
}
//核心判断
observer.mLastVersion = mVersion;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
}
当先设置数据时mVersion 会从-1自加到0,而此时mLastVersion 依旧为-1,此时if判断不满足会走下面的onChanged将mData数据分发出去。
去除粘性思路:在设置数据后,通过反射将mLastVersion与mVersion对齐,从而是上面的if判断命中,直接返回即可。
首先封装一个LiveDateBus 单例用于上层操作LiveData。
/**
* 是否去除粘性数据封装
*/
object LiveDateBus {
private const val TAG: String = "LiveDateBus-vivid"
private val bus : MutableMap<String,BusMutableLiveData<Any>> by lazy { HashMap() }
//对外操作接口
/**
* isStick : true 启用粘性数据 false 禁止粘性数据
*/
fun <T> with(key:String,type:Class<T>,isStick:Boolean = false):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() {
this.isStick = isStick
}
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
super.observe(owner, observer)
if(isStick){
Log.d(TAG, "observe: 启用粘性数据")
}else{
hook(observer = observer)
Log.d(TAG, "observe: 禁止粘性数据")
}
}
//通过反射修改
private fun hook(observer: Observer<in T>) {
val liveDateClass = LiveData::class.java
val mObserversField:Field = liveDateClass.getDeclaredField("mObservers")
mObserversField.isAccessible = true
val mObserverObject :Any = mObserversField.get(this)
val mObserversClass:Class<*> = mObserverObject.javaClass
val get :Method = mObserversClass.getDeclaredMethod("get", Any::class.java) // Any::class.java == Entry<K, V>
get.isAccessible = true
val invokeEntry : Any = get.invoke(mObserverObject, observer)
var observerWrapper :Any? = null
if(invokeEntry != null && invokeEntry is Map.Entry<*,*>){
observerWrapper = invokeEntry.value
}else{
throw NullPointerException("get invoke invokeEntry is error!")
}
if(observerWrapper == null){
throw NullPointerException("observerWrapper is Null.")
}
val superclass: Class<*> = observerWrapper.javaClass.superclass!!
val mLastVersion:Field = superclass.getDeclaredField("mLastVersion")
mLastVersion.isAccessible = true
val mVersion:Field = liveDateClass.getDeclaredField("mVersion")
mVersion.isAccessible = true
val mVersionaValue : Any = mVersion.get(this)
mLastVersion.set(observerWrapper,mVersionaValue)
}
}
}
其次设置数据:通过点击事件启动监听
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//禁止粘性数据
LiveDateBus.with("date", String::class.java,false).value = "测试数据1234567890"
//启用粘性数据
//LiveDateBus.with("date", String::class.java,true).value = "测试数据1234567890"
val button = findViewById<Button>(R.id.btn)
button.setOnClickListener {
startActivity(Intent(this,MainActivity2::class.java))
}
}
}
最后启动监听:
class MainActivity2 : AppCompatActivity() {
private val TAG: String = "MainActivity2-vivid"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
LiveDateBus.with("date", String::class.java).observe(this){
Log.d(TAG, "onCreate: 接受到数据是${it}")
}
}
}