網(wǎng)站首頁 編程語言 正文
LiveData簡(jiǎn)介
在日常安卓開發(fā)中,一些耗時(shí)的操比如列網(wǎng)絡(luò)請(qǐng)求,數(shù)據(jù)庫讀寫都不能在主線程執(zhí)行,必須開一條子線程去執(zhí)行這些耗時(shí)操作,但我們往往需要在這些耗時(shí)操作執(zhí)行完畢后更新UI,但安卓不能在子線程進(jìn)行UI的更新,這時(shí)我們只能通過創(chuàng)建一個(gè)Handler來切回到主線程進(jìn)行UI的更新,直到LiveData出現(xiàn),LiveData是一個(gè)可被觀察的數(shù)據(jù)容器,它將數(shù)據(jù)包裝起來,使數(shù)據(jù)成為被觀察者。當(dāng)數(shù)據(jù)發(fā)生改變時(shí),觀察者能夠及時(shí)得到通知。
LiveData用法
LiveData是一個(gè)數(shù)據(jù)容器,訂閱視圖的生命周期,在子線程通過postValue()切換到主線程來傳遞數(shù)據(jù)給觀察者,當(dāng)視圖是活動(dòng)的狀態(tài)下觀察者即可接受到數(shù)據(jù),LiveData是一個(gè)典型的觀察者模式。
class MainActivity : AppCompatActivity() {
private val mLiveData = MutableLiveData<String>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityMainBinding.inflate(LayoutInflater.from(baseContext))
setContentView(binding.root)
mLiveData.observe(this, {
binding.tvContent.text = it
})
Thread(BackgroundThread(mLiveData)).start()
}
private class BackgroundThread(liveData: MutableLiveData<String>) : Runnable {
private val mLive = WeakReference(liveData)
override fun run() {
mLive.apply {
get()?.apply {
postValue("hello LiveData")
}
}
}
}
}
數(shù)據(jù)訂閱過程
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
//1,判斷是否在主線程
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//2,通過owner,observer來構(gòu)建一個(gè)LifecycleBoundObserver
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//3,把observer存放到mObservers中
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//4,如果existing不為空代表觀察者已經(jīng)存在并且已經(jīng)綁定了生命周期,拋一個(gè)Exception來提示
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
//5,調(diào)用Lifecycle的addObserver()方法來訂閱生命周期
owner.getLifecycle().addObserver(wrapper);
}
1,先判斷當(dāng)前訂閱數(shù)據(jù)這個(gè)操作是否是在主線程中執(zhí)行,否則的話拋一個(gè)Exception
2,把owner,observer傳入到LifecycleBoundObserver構(gòu)建出一個(gè)LifecycleBoundObserver對(duì)象
3,調(diào)用mObservers.putIfAbsent()方法把觀察者放到觀察者集合中,mObservers是SafeIterableMap類型的集合類似Map,但它是通過鏈表的方式來實(shí)現(xiàn)Map接口,SafeIterableMap.putIfAbsent()方法與Map.put()方法不一樣,如果根據(jù)key獲取的value不為null,就將當(dāng)前的value返回,如果為null,就將當(dāng)前的鍵值對(duì)存儲(chǔ)起來,然后返回一個(gè)null
4,existing不為null,代表Observer存在,就拋一個(gè)Exception來提示開發(fā)者:無法添加具有不同生命周期的同一觀察者
5,existing為null,代表observer不存在,添加觀察者來觀察生命周期擁有者的生命周期,
當(dāng)我們的視圖的生命周期發(fā)生改變,LifecycleBoundObserver的onStateChange()方法就會(huì)被調(diào)用
PostValue過程
protected void postValue(T value) {
boolean postTask;
//判斷當(dāng)前是否正在下發(fā)數(shù)據(jù)
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
//如果正在下發(fā)數(shù)據(jù)則繼續(xù)下發(fā)數(shù)據(jù)
if (!postTask) {
return;
}
//構(gòu)建Handler并關(guān)聯(lián)主線程的Looper,回到主線程執(zhí)行run方法中的邏輯
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//在主線程中調(diào)用setValue來執(zhí)行數(shù)據(jù)下發(fā)邏輯
//noinspection unchecked
setValue((T) newValue);
}
};
當(dāng)調(diào)用postValue()方法是通過構(gòu)建一個(gè)Handler并關(guān)聯(lián)主線程的Looper來post一個(gè)Runnable來回到主線程執(zhí)行run方法里面的邏輯,而mPostValueRunnable的run()方法則調(diào)用了setValue()方法來實(shí)現(xiàn)數(shù)據(jù)的發(fā)送
SetValue過程
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
void dispatchingValue(@Nullable ObserverWrapper initiator) {
//1,判斷當(dāng)前是正在下發(fā)數(shù)據(jù)
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
//2,如果initiator不為空直接給initiator發(fā)送數(shù)據(jù)更新通知
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
/,3,否則遍歷所有observer
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
/4,發(fā)送數(shù)據(jù)更新通知
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
private void considerNotify(ObserverWrapper observer) {
5,如果當(dāng)前observer不是活動(dòng)狀態(tài),不下發(fā)數(shù)據(jù)
if (!observer.mActive) {
return;
}
6,如果當(dāng)前observer的狀態(tài)至少不是started狀態(tài)(可見狀態(tài)),resumed比started高一個(gè)級(jí)別(可觸摸狀態(tài))則不下發(fā)數(shù)據(jù)
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
7,判斷數(shù)據(jù)版本號(hào) 如果當(dāng)前observer的數(shù)據(jù)是最新的 則不下發(fā)數(shù)據(jù)
if (observer.mLastVersion >= mVersion) {
return;
}
8,記錄最新數(shù)據(jù)版本號(hào)
observer.mLastVersion = mVersion;
9,通知數(shù)據(jù)更新
observer.mObserver.onChanged((T) mData);
}
@Override
boolean shouldBeActive() {
判斷當(dāng)前狀態(tài)是否>=STARTED
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
1,檢查當(dāng)前是否在主線程
2, 每次調(diào)用setValue()方法版本號(hào)(mVersion)都進(jìn)行累加
3,把需要新數(shù)據(jù)賦值給mData
4,調(diào)用dispatchingValue來執(zhí)行數(shù)據(jù)下發(fā)
5,如果initiator不為null則直接給這個(gè)觀察者下發(fā)數(shù)據(jù)更新通知
6,否則遍歷所有的觀察者,逐個(gè)下發(fā)數(shù)據(jù)更新通知
7,判斷當(dāng)前的observer是否為活動(dòng)狀態(tài),不是活動(dòng)狀態(tài)不下發(fā)數(shù)據(jù),這也就是為什么我們界面不可見時(shí)數(shù)據(jù)不會(huì)更新的原因(onStop狀態(tài))
8,判斷當(dāng)前的observer是否是resumed狀態(tài),不是resumed狀態(tài)不下發(fā)數(shù)據(jù),這就是為什么當(dāng)我們的頁面可見但不可觸摸時(shí)數(shù)據(jù)不更新的原因(onPause狀態(tài))
9,比對(duì)數(shù)據(jù)版本號(hào),如果當(dāng)前observer的數(shù)據(jù)是最新數(shù)據(jù)則不需要下發(fā)
10,記錄數(shù)據(jù)版本號(hào)并通知observer數(shù)據(jù)更新,回調(diào)observer的onChanged()方法
生命周期變化
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
1,如果當(dāng)前的狀態(tài)為destroyed就移除observer
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
2,更新狀態(tài)并下發(fā)數(shù)據(jù)
activeStateChanged(shouldBeActive());
}
void activeStateChanged(boolean newActive) {
3,如果新狀態(tài)和當(dāng)前狀態(tài)一致的話不需要更新
if (newActive == mActive) {
return;
}
4,記錄新狀態(tài)
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
5,如果是活動(dòng)狀態(tài) 下發(fā)數(shù)據(jù)
if (mActive) {
dispatchingValue(this);
}
}
在訂閱數(shù)據(jù)那一刻(即調(diào)用LiveData.observer())就構(gòu)建了一個(gè)LifecycleBoundObserver并且讓LifecycleBoundObserver訂閱了頁面生命周期,所以當(dāng)頁面的生命周期發(fā)生改變,LifecycleBoundObserver的onStateChanged()方法都會(huì)被調(diào)用
1,如果當(dāng)前頁面的狀態(tài)為destroyed(即銷毀狀態(tài)),則移除觀察者
2,更新狀態(tài)并下發(fā)數(shù)據(jù)
3,判斷當(dāng)前observer的狀態(tài)跟新狀態(tài)是否一致,如果時(shí)是則不需要更新狀態(tài)以及數(shù)據(jù)
4,記錄當(dāng)前observer的狀態(tài)
5,調(diào)用dispatchingValue()并傳入當(dāng)前observer,執(zhí)行準(zhǔn)確下發(fā)數(shù)據(jù)業(yè)務(wù)
原文鏈接:https://blog.csdn.net/qq_42359647/article/details/124980451
相關(guān)推薦
- 2022-05-23 iOS實(shí)現(xiàn)全局懸浮按鈕_IOS
- 2022-12-05 Python應(yīng)用開發(fā)之實(shí)現(xiàn)串口通信_(tái)python
- 2022-08-03 python工具之清理?Markdown?中沒有引用的圖片_python
- 2024-01-13 nvm命令
- 2022-11-05 Android開發(fā)使用Databinding實(shí)現(xiàn)關(guān)注功能mvvp_Android
- 2023-04-27 python請(qǐng)求域名requests.(url?=?地址)報(bào)錯(cuò)_python
- 2023-01-09 React應(yīng)用框架Dva數(shù)據(jù)流向原理總結(jié)分析_React
- 2022-06-08 Spring Cloud Nacos 配置變更感知
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支