升職加薪學習旅程 -- 設置防止數(shù)據(jù)倒灌+ 永久監(jiān)聽的LiveData

首先這里是使用了GitHub中UnPeek-LiveData的代碼,用來構造一個AntiBackFlowLiveData,"數(shù)據(jù)倒灌"這個也是在里面有解釋就不做贅述

open class AntiBackFlowLiveData<T> : LiveData<T> {

    constructor() : super()

    constructor(value: T) : super(value)

    private var startVersion: Int = -1

    private val mCurrentVersion = AtomicInteger(startVersion)

    /**
     *  當 liveData 用作 event 時成艘,可使用該方法觀察 "生命周期敏感" 非粘性消息
     **/
    override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
        super.observe(owner, createObserverWrapper(observer, mCurrentVersion.get()))
    }

    /**
     *  當 liveData 用作 event 時赏半,可使用該方法觀察 "生命周期不敏感" 非粘性消息
     **/
    override fun observeForever(observer: Observer<in T>) {
        super.observeForever(createObserverWrapper(observer, mCurrentVersion.get()))
    }

    /**
     *  當 liveData 用作 state 時,可使用該方法來觀察 "生命周期不敏感" 粘性消息
     **/
    fun observeSticky(owner: LifecycleOwner, observer: Observer<in T>) {
        super.observe(owner, createObserverWrapper(observer, startVersion))
    }

    public override fun setValue(value: T) {
        mCurrentVersion.getAndIncrement()
        super.setValue(value)
    }

    public override fun postValue(value: T) {
        super.postValue(value)
    }

    private fun createObserverWrapper(observer: Observer<in T>, version: Int): ObserverWrapper<T> {
        return ObserverWrapper(observer, version)
    }

    override fun removeObserver(observer: Observer<in T>) {
        if (observer::class.java.isAssignableFrom(ObserverWrapper::class.java)) {
            super.removeObserver(observer)
        } else {
            super.removeObserver(createObserverWrapper(observer, startVersion))
        }
    }

    fun clear() {
        super.setValue(null)
    }

    inner class ObserverWrapper<T>(val observer: Observer<in T>, var version: Int) : Observer<T> {

        override fun onChanged(t: T?) {
            if (mCurrentVersion.get() > version) {
                observer.onChanged(t)
            }
        }

        override fun equals(other: Any?): Boolean {
            if (other == null || other::class.java != this::class.java) {
                return false
            }
            if (this === other) {
                return true
            }

            return Objects.equals(observer, (other as ObserverWrapper<*>).observer)
        }

        override fun hashCode(): Int {
            return Objects.hash(observer)
        }
    }
}

這里使用了自己的一個Version作為版本控制,避免數(shù)據(jù)的倒灌
為了方便使用一個全局的"AppViewModel"來進行一個Event的發(fā)送,所以在理論上是使用LiveData.observeForever這個方法來進行監(jiān)聽,但是在使用observeForever這個方法時需要在activity/Fragment被銷毀是remove掉這個lifecycleOwner,所以這里對LiveData進行一個生命周期的擴展,讓我們在使用的時候只需要監(jiān)聽,不需要去管理其他的生命周期

class ForeverLiveData<T> : AntiBackFlowLiveData<T>(), DefaultLifecycleObserver {
    private val mOwners: MutableList<LifecycleOwner> = mutableListOf()
    private val ownerMap  = mutableMapOf<Int,Observer<in T>>()

    fun observeForever(lifecycleOwner: LifecycleOwner, observer: Observer<in T>) {
        super.observeForever(observer)
        lifecycleOwner.lifecycle?.addObserver(this)
        mOwners.add(lifecycleOwner)
        ownerMap[lifecycleOwner.hashCode()] = observer
    }

    override fun onDestroy(owner: LifecycleOwner) {
        for ((key,value) in ownerMap){
            if (key == owner.hashCode()){
                this.removeObserver(value)
                ownerMap.remove(key)
            }
        }
        mOwners.forEach {
            if (owner == it) {
                it.lifecycle.removeObserver(this)
                mOwners.remove(it)
            }
        }
        super.onDestroy(owner)
    }
}

上述代碼繼承了DefaultLifecycleObserver ,并在onDestroy方法里面進行回收,避免了手動去調用移除

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末淆两,一起剝皮案震驚了整個濱河市断箫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌秋冰,老刑警劉巖仲义,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異剑勾,居然都是意外死亡埃撵,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進店門虽另,熙熙樓的掌柜王于貴愁眉苦臉地迎上來暂刘,“玉大人,你說我怎么就攤上這事捂刺∫ゼ穑” “怎么了?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵叠萍,是天一觀的道長芝发。 經(jīng)常有香客問我绪商,道長苛谷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任格郁,我火速辦了婚禮腹殿,結果婚禮上,老公的妹妹穿的比我還像新娘例书。我一直安慰自己锣尉,他們只是感情好,可當我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布决采。 她就那樣靜靜地躺著自沧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上拇厢,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天爱谁,我揣著相機與錄音,去河邊找鬼孝偎。 笑死访敌,一個胖子當著我的面吹牛,可吹牛的內容都是我干的衣盾。 我是一名探鬼主播寺旺,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼势决!你這毒婦竟也來了阻塑?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤徽龟,失蹤者是張志新(化名)和其女友劉穎叮姑,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體据悔,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡传透,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了极颓。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朱盐。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖菠隆,靈堂內的尸體忽然破棺而出兵琳,到底是詐尸還是另有隱情,我是刑警寧澤骇径,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布躯肌,位于F島的核電站,受9級特大地震影響破衔,放射性物質發(fā)生泄漏清女。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一晰筛、第九天 我趴在偏房一處隱蔽的房頂上張望嫡丙。 院中可真熱鬧,春花似錦读第、人聲如沸曙博。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽父泳。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惠窄,已是汗流浹背逝她。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留睬捶,地道東北人黔宛。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像擒贸,于是被迫代替她去往敵國和親臀晃。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內容