欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android Jetpack組件庫(kù)LiveData源碼深入探究

 更新時(shí)間:2022年09月20日 08:31:14   作者:艾陽Blog  
LiveData是Jetpack組件的一部分,更多的時(shí)候是搭配ViewModel來使用,相對(duì)于Observable,LiveData的最大優(yōu)勢(shì)是其具有生命感知的,換句話說,LiveData可以保證只有在組件( Activity、Fragment、Service)處于活動(dòng)生命周期狀態(tài)的時(shí)候才會(huì)更新數(shù)據(jù)

Android Jetpack之ViewModel、LiveData

Android Jetpack之LifeCycle

Android Jetpack之DataBinding+ViewModel+LiveData+Room

前言

Jetpack是一個(gè)由多個(gè)技術(shù)庫(kù)組成的套件,可幫助開發(fā)者遵循最佳做法,減少樣板代碼并編寫可在各種Android版本和設(shè)備中一致運(yùn)行的代碼,讓開發(fā)者精力集中編寫重要的代碼。

一、LiveData

LiveData 是一種持有可被觀察的數(shù)據(jù)存儲(chǔ)類。和其他可被觀察的類不同的是LiveData 可以在 Activity ,fragment 或者 service 生命周期發(fā)生改變時(shí)通知更新。LiveData 已經(jīng)是必不可少的一環(huán)了,例如 MVVM 以及 MVI 開發(fā)模式中,都用到了 LiveData。

(注意??源碼是Java代碼)

LIveData 的優(yōu)勢(shì):

  • 確保界面符合數(shù)據(jù)狀態(tài):數(shù)據(jù)發(fā)生變化時(shí),就會(huì)通知觀察者。我們可以再觀察者回調(diào)中更新界面,這樣就無需在數(shù)據(jù)改變后手動(dòng)更新界面了。
  • 沒有內(nèi)存泄漏,因?yàn)殛P(guān)聯(lián)了生命周期,頁面銷毀后會(huì)進(jìn)行自我清理。
  • 不會(huì)因?yàn)锳ctivity 停止而導(dǎo)致崩潰,頁面處于非活躍狀態(tài)時(shí),他不會(huì)接收到任何 LiveData 事件。
  • 共享資源,可以使用單例模式擴(kuò)展 LiveData 對(duì)象,以便在應(yīng)用中共享他們。
  • 屏幕翻轉(zhuǎn)數(shù)據(jù)狀態(tài)保留
  • 不再需要手動(dòng)處理生命周期
  • 數(shù)據(jù)始終保持最新狀態(tài)

二、使用案例

LiveData 是一種可用于任何數(shù)據(jù)的封裝容器,通常 LiveData 存儲(chǔ)在 ViewModel 對(duì)象中。

class JokesDetailViewModel : ViewModel() {
    //創(chuàng)建 LiveData
    private val _state by lazy { MutableLiveData<JokesUIState>() }
    val state : LiveData<JokesUIState> = _state
    private fun loadChildComment(page: Int, commentId: Int, parentPos: Int, curPos: Int) {
        viewModelScope.launch {
            launchHttp {
                jokesApi.jokesCommentListItem(commentId, page)//請(qǐng)求數(shù)據(jù)
            }.toData {
                //通知觀察者
                _state.value = JokesUIState.LoadMoreChildComment(it.data, parentPos, curPos)
            }
        }
     }
}    
//觀察 LiveData
viewModel.state.observe(this, Observer {
    //更新 UI 
})

三、LiveData 實(shí)現(xiàn)原理

  • Observer:觀察者接口;
  • LiveData:發(fā)送已經(jīng)添加觀察的邏輯都在其中;
  • ObserverWrapper:抽象的觀察者包裝類;
  • LifecycleBoundleObserver:繼承 ObserverWrapper;
  • LifecycleEventObserver,生命周期相關(guān)回調(diào);

observe(this,Observer{})

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        //如果已經(jīng)銷毀,直接退出
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            return;
        }
        //包裝類(下面源碼)
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //判斷是否已添加
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && !existing.isAttachedTo(owner)) {
           //....
        }
        //之前添加過
        if (existing != null) {
            return;
        }
        //注冊(cè) lifecycle,生命周期改變時(shí)會(huì)回調(diào)
        owner.getLifecycle().addObserver(wrapper);
    }

LifecycleBoundObserver(owner, observer)

class LifecycleBoundObserver 
                extends ObserverWrapper implements LifecycleEventObserver {
    @NonNull
    final LifecycleOwner mOwner;
    LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
        super(observer);
        mOwner = owner;
    }
    //當(dāng)前狀態(tài)大于或者等于 STARTED 返回 true
    @Override
    boolean shouldBeActive() {
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }
    //生命周期相關(guān)回調(diào)
    @Override
    public void onStateChanged(@NonNull LifecycleOwner source,
            @NonNull Lifecycle.Event event) {
        Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
        //如果已經(jīng)銷毀,移除觀察者 
        if (currentState == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        Lifecycle.State prevState = null;
       //循環(huán)更新狀態(tài)
        while (prevState != currentState) {
            prevState = currentState;
            //修改活躍狀態(tài)
            activeStateChanged(shouldBeActive());
            currentState = mOwner.getLifecycle().getCurrentState();
        }
    }
    @Override
    boolean isAttachedTo(LifecycleOwner owner) {
        return mOwner == owner;
    }
    @Override
    void detachObserver() {
        mOwner.getLifecycle().removeObserver(this);
    }
}
  • 繼承 ObserverWrapper 的包裝類--activeStateChanged(..)方法。
  • 實(shí)現(xiàn)LifecycleEventObserver 接口--onStateChanged(..)方法。

ObserverWrapper.activeStateChanged()

void activeStateChanged(boolean newActive) {
  //如果等于之前狀態(tài)
  if (newActive == mActive) {
    return;
  }
  mActive = newActive;
  //活躍 +1,不活躍 -1 (下面有源碼)
  changeActiveCounter(mActive ? 1 : -1);
  //如果狀態(tài)變成了活躍狀態(tài),直接調(diào)用 dispatchingValue,傳入當(dāng)前的觀察者
  if (mActive) {
    dispatchingValue(this); //(下面有源碼)
  }
}
//修改活躍數(shù)量
void changeActiveCounter(int change) {
    int previousActiveCount = mActiveCount;//之前活躍的數(shù)量
    mActiveCount += change;//總活躍數(shù)量
    if (mChangingActiveState) {//如果正在更改,退出
        return;
    }
    mChangingActiveState = true;//更改中
    try {
        while (previousActiveCount != mActiveCount) {
            boolean needToCallActive = previousActiveCount == 0 && mActiveCount > 0;
            boolean needToCallInactive = previousActiveCount > 0 && mActiveCount == 0;
            previousActiveCount = mActiveCount;
            //如果當(dāng)前是第一個(gè)激活的,調(diào)用 onActive
            if (needToCallActive) {
                onActive();//當(dāng)活動(dòng)的觀察者從0 變成 1的時(shí)候調(diào)用
            //如果沒有激活的為 0 ,調(diào)用 onInactive  
            } else if (needToCallInactive) {
                onInactive();//活躍的觀察者變成 0 時(shí)調(diào)用
            }
        }
    } finally {
        mChangingActiveState = false;
    }
}
//分發(fā)數(shù)據(jù)
void dispatchingValue(@Nullable ObserverWrapper initiator) {
  if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;  //如果正在分發(fā),退出  
    }
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        //如果觀察者不為空 
        if (initiator != null) {
            considerNotify(initiator);//對(duì)數(shù)據(jù)進(jìn)行派發(fā),通知觀察者
            initiator = null;
        } else {
          //如果為空,遍歷所有的觀察者,將數(shù)據(jù)發(fā)送給所有觀察者
            for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}
//數(shù)據(jù)進(jìn)行派發(fā),通知觀察者
private void considerNotify(ObserverWrapper observer) {
    if (!observer.mActive) {
        return;
    }
    //再次進(jìn)行判斷,如果不活躍,則會(huì)更新狀態(tài),然后退出
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    //觀察者版本是否低于當(dāng)前的版本
    //初始值 mLastVersion 為 -1,mVersion 為 0
    //小于等于表示沒有需要更新的數(shù)據(jù)
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    //更新版本
    observer.mLastVersion = mVersion;
    //通知觀察者
    observer.mObserver.onChanged((T) mData);
}

梳理流程:

1、通過 observe 添加一個(gè)觀察者,這個(gè)觀察者會(huì)被 LifecycleBoundObserver 進(jìn)行一個(gè)封裝,LifecycleBoundObserver繼承 ObserverWrapper,并且實(shí)現(xiàn)了 LifecycleEventObserver。之后就會(huì)將觀察添加到 Observers 中,最后注冊(cè)頁面生命周期的 observer。

2、當(dāng)生命周期發(fā)生變化后,就會(huì)回調(diào)到 LifecycleBoundObserve 中的 onStateChanged 方法中。如果生命周期是銷毀的,就會(huì)移除觀察者,如果不是就會(huì)循環(huán)更新當(dāng)前狀態(tài)。

3、在更新狀態(tài)的時(shí)候就會(huì)判斷是否為活躍狀態(tài),如果是活躍狀態(tài)就會(huì)進(jìn)行分發(fā),分發(fā)的時(shí)候如果觀察者為 null ,就會(huì)遍歷所有的觀察者進(jìn)行分發(fā),否則就分發(fā)傳入的觀察者。

4、最后會(huì)再次判斷活躍狀態(tài),已經(jīng)判斷觀察者版本是否低于當(dāng)前版本,如果都滿足,就會(huì)更新觀察者。

onActive 與 onInactive

如果觀察者的生命周期處于 STARTED 或者 RESUMED 狀態(tài),LiveData 就會(huì)認(rèn)為觀察者處于活躍狀態(tài)。

例如,下載數(shù)據(jù)需要在活躍狀態(tài)下進(jìn)行,或者需要實(shí)時(shí)的監(jiān)聽后臺(tái)數(shù)據(jù),就可以重新下面方法,并完成對(duì)應(yīng)邏輯。

class StockLiveData(url: String) : LiveData<String>() {
    private val downloadManager = DownloadManager(url)
    override fun onActive() {
      if(!downloadManager.isStart()){
          downloadManager.start()
      }
    }
    override fun onInactive() {
         downloadManager.stop()
    }
}

當(dāng)具有活躍的觀察者時(shí),就會(huì)調(diào)用 onActive 方法。

當(dāng)沒有任何活躍的觀察者時(shí),就會(huì)調(diào)用 onInactive 方法。

當(dāng)然這只是我想到的場(chǎng)景,開發(fā)中可以根據(jù)不同的業(yè)務(wù)場(chǎng)景做出不同的判斷。

四、LiveData 相關(guān)源碼

MutableLiveData

由于 LiveData 的發(fā)送數(shù)據(jù)方法是 protected 修飾私有受保護(hù)的,所以不能直接調(diào)用。因此使用MutableLiveData 繼承 LiveData 將發(fā)送數(shù)據(jù)的方法改為了 public。

public class MutableLiveData<T> extends LiveData<T> {
    /**
     * Creates a MutableLiveData initialized with the given {@code value}.
     */
    public MutableLiveData(T value) {
        super(value);
    }
    /**
     * Creates a MutableLiveData with no value assigned to it.
     */
    public MutableLiveData() {
        super();
    }
    @Override
    public void postValue(T value) {
        super.postValue(value);
    }
    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}

Transformations.map()

在數(shù)據(jù)分發(fā)給觀察者之前對(duì)其中存儲(chǔ)的值進(jìn)行更改,返回一個(gè)新的 LiveData,可以使用此方法。

val strLiveData = MutableLiveData<String>()
 val strLengthLiveData = Transformations.map(strLiveData) {
    it.length
 }
 strLiveData.observe(this) {
   Log.e("---345---> str:", "$it");
 }
 strLengthLiveData.observe(this) {
  Log.e("---345---> strLength:", "$it");
 }
strLiveData.value = "hello word"
E/---345---> str:: hello word
E/---345---> strLength:: 10

Transformations.switchMap()

對(duì)上面的做了個(gè)判斷,根據(jù)不同的需求返回不同的 LiveData。也可以通過 id 去判斷,返回對(duì)應(yīng)的 livedata 即可。

val idLiveData = MutableLiveData<Int>()
val userLiveData = Transformations.switchMap(idLiveData) { id->
      getUser(id)
}

合并多個(gè) LiveData

val live1 = MutableLiveData<String>()
val live2 = MutableLiveData<String>()
val mediator = MediatorLiveData<String>()
mediator.addSource(live1) {
  mediator.value  = it
  Log.e("---345---> live1", "$it");
}
mediator.addSource(live2){
  mediator.value  = it
  Log.e("---345---> live2", "$it");
}
mediator.observe(this, Observer {
  Log.e("---345---> mediator", "$it");
})
live1.value = "hello"
E/---345---> mediator: hello
E/---345---> live1: hello

通過 MediatorLiveData 將兩個(gè) MutableLiveData 合并到一起,這樣當(dāng)任何一個(gè)發(fā)生變化,MediatorLiveData 都可以感知到。

五、LiveData分發(fā)問題

數(shù)據(jù)粘性事件

例如再?zèng)]有觀察者的時(shí)候發(fā)送數(shù)據(jù),此時(shí) mVersion +1,等到真正添加了觀察者后,生命周期也是活躍的,那么就會(huì)將這個(gè)數(shù)據(jù)重新分發(fā)到觀察者。所以說發(fā)送數(shù)據(jù)這個(gè)操作是粘性的。

如果需要去除粘性事件,可以在添加完 observe 后去通過反射修改 mVersion 和 觀察者包裝類中的 mLastVersion 的值,將 mVersion 賦值給 mLastVersion 即可去掉粘性事件。

數(shù)據(jù)倒灌現(xiàn)象

一般情況下,LiveData 都是存放在 ViewModel 中的,當(dāng)Activity重建的時(shí)候,觀察者會(huì)被 remove 掉,重建后會(huì)添加一個(gè)新的觀察者,添加后新的觀察者版本號(hào)就是 -1,所以就會(huì)出現(xiàn)數(shù)據(jù)再次被接收到。

這種解決方式和上面一樣,反射修改版本號(hào)就可以解決。非活躍狀態(tài)的觀察者轉(zhuǎn)為活躍狀態(tài)后,只能接收到最后一次發(fā)送的數(shù)據(jù)。一般情況下我們都需要的是最新數(shù)據(jù),如果非要所有數(shù)據(jù),只能重寫 LiveData 了。

到此這篇關(guān)于Android Jetpack組件庫(kù)LiveData源碼深入探究的文章就介紹到這了,更多相關(guān)Android Jetpack LiveData內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論