-
Notifications
You must be signed in to change notification settings - Fork 629
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
208 additions
and
210 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
116 changes: 49 additions & 67 deletions
116
JetpackMvvm/src/main/java/me/hgj/jetpackmvvm/callback/livedata/UnPeekLiveData.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,83 +1,65 @@ | ||
package me.hgj.jetpackmvvm.callback.livedata | ||
|
||
import androidx.lifecycle.LifecycleOwner | ||
import androidx.lifecycle.LiveData | ||
import androidx.lifecycle.MutableLiveData | ||
import androidx.lifecycle.Observer | ||
import me.hgj.jetpackmvvm.ext.util.notNull | ||
import java.util.* | ||
|
||
/** | ||
* 防止数据倒灌的LiveData | ||
* @author : hgj | ||
* @date : 2020/7/16 | ||
* 作者 : hegaojian | ||
* 时间 : 2019/12/17 | ||
* 仅分发 owner observe 后 才新拿到的数据 | ||
* 可避免共享作用域 VM 下 liveData 被 observe 时旧数据倒灌的情况 | ||
*/ | ||
|
||
class UnPeekLiveData<T> : MutableLiveData<T>() { | ||
private var isCleaning = false | ||
private var hasHandled = true | ||
private var isDelaying = false | ||
private val mTimer = Timer() | ||
private var mTask: TimerTask? = null | ||
private var DELAY_TO_CLEAR_EVENT = 1000 | ||
|
||
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) { | ||
super.observe(owner, Observer { | ||
if (isCleaning) { | ||
hasHandled = true | ||
isDelaying = false | ||
isCleaning = false | ||
return@Observer | ||
} | ||
if (!hasHandled) { | ||
hasHandled = true | ||
isDelaying = true | ||
observer.onChanged(it) | ||
} else if (isDelaying) { | ||
observer.onChanged(it) | ||
} | ||
}) | ||
override fun observe( | ||
owner: LifecycleOwner, | ||
observer: Observer<in T> | ||
) { | ||
super.observe(owner, observer) | ||
hook(observer) | ||
} | ||
|
||
override fun observeForever(observer: Observer<in T>) { | ||
super.observeForever(Observer { | ||
if (isCleaning) { | ||
hasHandled = true | ||
isDelaying = false | ||
isCleaning = false | ||
return@Observer | ||
private fun hook(observer: Observer<in T>) { | ||
val liveDataClass = LiveData::class.java | ||
try { | ||
//获取field private SafeIterableMap<Observer<T>, ObserverWrapper> mObservers | ||
val mObservers = liveDataClass.getDeclaredField("mObservers") | ||
mObservers.isAccessible = true | ||
//获取SafeIterableMap集合mObservers | ||
val observers = mObservers[this] | ||
val observersClass: Class<*> = observers.javaClass | ||
//获取SafeIterableMap的get(Object obj)方法 | ||
val methodGet = | ||
observersClass.getDeclaredMethod("get", Any::class.java) | ||
methodGet.isAccessible = true | ||
//获取到observer在集合中对应的ObserverWrapper对象 | ||
val objectWrapperEntry = methodGet.invoke(observers, observer) | ||
var objectWrapper: Any? = null | ||
if (objectWrapperEntry is Map.Entry<*, *>) { | ||
objectWrapper = objectWrapperEntry.value | ||
} | ||
if (!hasHandled) { | ||
hasHandled = true | ||
isDelaying = true | ||
observer.onChanged(it) | ||
} else if (isDelaying) { | ||
observer.onChanged(it) | ||
} | ||
}) | ||
} | ||
|
||
/** | ||
* 重写的 setValue 方法 | ||
* @param value | ||
*/ | ||
override fun setValue(value: T?) { | ||
hasHandled = false | ||
isDelaying = false | ||
super.setValue(value) | ||
mTask.notNull({ | ||
it.cancel() | ||
mTimer.purge() | ||
}) | ||
mTask = object : TimerTask() { | ||
override fun run() { | ||
clear() | ||
if (objectWrapper == null) { | ||
throw NullPointerException("ObserverWrapper can not be null") | ||
} | ||
//获取ObserverWrapper的Class对象 LifecycleBoundObserver extends ObserverWrapper | ||
val wrapperClass: Class<*>? = objectWrapper.javaClass.superclass | ||
//获取ObserverWrapper的field mLastVersion | ||
val mLastVersion = | ||
wrapperClass!!.getDeclaredField("mLastVersion") | ||
mLastVersion.isAccessible = true | ||
//获取liveData的field mVersion | ||
val mVersion = liveDataClass.getDeclaredField("mVersion") | ||
mVersion.isAccessible = true | ||
val mV = mVersion[this] | ||
//把当前ListData的mVersion赋值给 ObserverWrapper的field mLastVersion | ||
mLastVersion[objectWrapper] = mV | ||
mObservers.isAccessible = false | ||
methodGet.isAccessible = false | ||
mLastVersion.isAccessible = false | ||
mVersion.isAccessible = false | ||
} catch (e: Exception) { | ||
e.printStackTrace() | ||
} | ||
mTimer.schedule(mTask, DELAY_TO_CLEAR_EVENT.toLong()) | ||
} | ||
|
||
private fun clear() { | ||
hasHandled = true | ||
isDelaying = false | ||
} | ||
} |
Oops, something went wrong.