日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

詳解Android JetPack之LiveData的工作原理

瀏覽:33日期:2022-09-20 13:14:07
前言

本篇文章主要講解LiveData工作的原理,如果還不知道LiveData如何用的話,請參考官方文檔。 LiveData的講解涉及到了Lifecycle的知識,如果你還不了解LifeCycle,請參考文檔LifeCycle介紹。

介紹

LiveData是一個數據持有類,它可以通過添加觀察者被其他組件觀察其變更。不同于普通的觀察者,它最重要的特性就是遵從應用程序的生命周期,如在Activity中如果數據更新了但Activity已經是destroy狀態,LivaeData就不會通知Activity(observer)。當然。LiveData的優點還有很多,如不會造成內存泄漏等。

LiveData通常會配合ViewModel來使用,ViewModel負責觸發數據的更新,更新會通知到LiveData,然后LiveData再通知活躍狀態的觀察者。

原理分析

下面直接看代碼:

public class UserProfileViewModel extends ViewModel { private String userId; private MutableLiveData<User> user; private UserRepository userRepo; public void init(String userId) { this.userId = userId; userRepo = new UserRepository(); user = userRepo.getUser(userId); } public void refresh(String userId) { user = userRepo.getUser(userId); } public MutableLiveData<User> getUser() { return user; }}

上面UserProfileViewModel內部持有 UserRepository 中 MutableLiveData的引用,并且提供了獲取 MutableLiveData 的方法 getUser(),UserRepository 負責從網絡或數據庫中獲取數據并封裝成 MutableLiveData 然后提供給 ViewModel。

我們在 UserProfileFragment 中為 MutableLiveData 注冊觀察者,如下:

@Overridepublic void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); String userId = getArguments().getString(UID_KEY); viewModel = ViewModelProviders.of(this).get(UserProfileViewModel.class); viewModel.init(userId); //標注1 viewModel.getUser().observe(UserProfileFragment.this, new Observer<User>() { @Override public void onChanged(@Nullable User user) { if (user != null) { tvUser.setText(user.toString()); } } });}

看標注1處,viewModel.getUser()獲取到 MutableLiveData 也就是我們的 LiveData,然后調用 LiveData的observer方法,并把UserProfileFragment作為參數傳遞進去。observer() 方法就是我們分析的入口了,接下來我們看LiveData的observer()方法都做了什么:

@MainThreadpublic void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) { //標注1 if (owner.getLifecycle().getCurrentState() == DESTROYED) { // ignore return; } //標注2 LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer); ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper); if (existing != null && !existing.isAttachedTo(owner)) { throw new IllegalArgumentException('Cannot add the same observer' + ' with different lifecycles'); } if (existing != null) { return; } owner.getLifecycle().addObserver(wrapper);}

可以看到,UserProfileFragment 是作為 LifeCycleOwner 參數傳進來的,如果你的support包版本大于等于26.1.0,support包中的 Fragment 會默認繼承自 LifecycleOwner,而 LifecycleOwner 可獲取到該組件的 LifeCycle,也就知道了 UserProfileFragment 組件的生命周期(在這里默認大家已經了解過LifeCycle了)。

看標注1處,如果我們的 UserProfileFragment 組件已經是destroy狀態的話,將直接返回,不會被加入觀察者行列。如果不是destroy狀態,就到標注2處,新建一個 LifecycleBoundObserver 將我們的 LifecycleOwner 和 observer保存起來,然后調用 mObservers.putIfAbsent(observer, wrapper) 將observer和wrapper分別作為key和value存入Map中,putIfAbsent()方法會判斷如果 value 已經能夠存在,就返回,否則返回null。 如果返回existing為null,說明以前沒有添加過這個觀察者,就將 LifecycleBoundObserver 作為 owner 生命周期的觀察者,也就是作為 UserProfileFragment 生命周期的觀察者。

我們看下LifecycleBoundObserver 源碼:

class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver { @NonNull final LifecycleOwner mOwner; LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) { super(observer); mOwner = owner; } @Override boolean shouldBeActive() { return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED); } @Override public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) { if (mOwner.getLifecycle().getCurrentState() == DESTROYED) { removeObserver(mObserver); return; } activeStateChanged(shouldBeActive()); } @Override boolean isAttachedTo(LifecycleOwner owner) { return mOwner == owner; } @Override void detachObserver() { mOwner.getLifecycle().removeObserver(this); }}

代碼并不多,LifecycleBoundObserver 繼承自 ObserverWrapper 并實現了 GenericLifecycleObserver接口,而 GenericLifecycleObserver 接口又繼承自 LifecycleObserver 接口,那么根據 Lifecycle 的特性,實現了LifecycleObserver接口并且加入 LifecycleOwner 的觀察者里就可以感知或主動獲取 LifecycleOwner 的狀態。

好了,看完了觀察者,那么我們的LiveData什么時候會通知觀察者呢?不用想,肯定是數據更新的時候,而數據的更新是我們代碼自己控制的,如請求網絡返回User信息后,我們會主動將User放入MutableLiveData中,這里我在UserRepository中直接模擬網絡請求如下:

public class UserRepository { final MutableLiveData<User> data = new MutableLiveData<>(); public MutableLiveData<User> getUser(final String userId) { if ('xiasm'.equals(userId)) { data.setValue(new User(userId, '夏勝明')); } else if ('123456'.equals(userId)) { data.setValue(new User(userId, '哈哈哈')); } else { data.setValue(new User(userId, 'unknow')); } return data; }}

當調用getUser()方法的時候,我們調用MutableLiveData的setValue()方法將數據放入LiveData中,這里MutableLiveData實際上就是繼承自LiveData,沒有什么特別:

public class MutableLiveData<T> extends LiveData<T> { @Override public void postValue(T value) { super.postValue(value); } @Override public void setValue(T value) { super.setValue(value); }}

setValue()在放入User的時候必須在主線程,否則會報錯,而postValue則沒有這個檢查,而是會把數據傳入到主線程。我們直接看setValue()方法:

@MainThreadprotected void setValue(T value) { assertMainThread('setValue'); mVersion++; mData = value; dispatchingValue(null);}

首先調用assertMainThread()檢查是否在主線程,接著將要更新的數據賦給mData,然后調用 dispatchingValue()方法并傳入null,將數據分發給各個觀察者,如我們的 UserProfileFragment。看 dispatchingValue()方法實現:

private void dispatchingValue(@Nullable ObserverWrapper initiator) { if (mDispatchingValue) { mDispatchInvalidated = true; return; } mDispatchingValue = true; do { mDispatchInvalidated = false; //標注1 if (initiator != null) { considerNotify(initiator); initiator = null; } else { //標注2 for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator = mObservers.iteratorWithAdditions(); iterator.hasNext(); ) { considerNotify(iterator.next().getValue()); if (mDispatchInvalidated) { break; } } } } while (mDispatchInvalidated); mDispatchingValue = false;}

從標注1可以看出,dispatchingValue()參數傳null和不傳null的區別就是如果傳null將會通知所有的觀察者,反之僅僅通知傳入的觀察者。我們直接看標注2,通知所有的觀察者通過遍歷 mObservers ,將所有的 ObserverWrapper 拿到,實際上就是我們上面提到的 LifecycleBoundObserver,通知觀察者調用considerNotify()方法,這個方法就是通知的具體實現了。

private void considerNotify(ObserverWrapper observer) { if (!observer.mActive) { return; } // Check latest state b4 dispatch. Maybe it changed state but we didn’t get the event yet. // // we still first check observer.active to keep it as the entrance for events. So even if // the observer moved to an active state, if we’ve not received that event, we better not // notify for a more predictable notification order. if (!observer.shouldBeActive()) { observer.activeStateChanged(false); return; } if (observer.mLastVersion >= mVersion) { return; } observer.mLastVersion = mVersion; //noinspection unchecked observer.mObserver.onChanged((T) mData);}

如果觀察者不是活躍狀態,將不會通知此觀察者,看最后一行,observer.mObserver.onChanged((T) mData),observer.mObserver就是我們調用LiveData的observer()方法傳入的 Observer,然后調用 Observer 的 onChanged((T) mData)方法,將保存的數據mData傳入,也就實現了更新。在看下我們實現的Observer:

viewModel.getUser().observe(UserProfileFragment.this, new Observer<User>() { @Override public void onChanged(@Nullable User user) { if (user != null) { tvUser.setText(user.toString()); } }});

如果哪個控件要根據user的變更而及時更新,就在onChanged()方法里處理就可以了。到這里,LiveData已經能夠分析完了,其實LiveData的實現還是要依賴于Lifecycle。

以上就是詳解Android JetPack之LiveData的工作原理的詳細內容,更多關于Android JetPack之LiveData的工作原理的資料請關注好吧啦網其它相關文章!

標簽: Android
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
欧美激情在线精品一区二区三区| 最新日韩av| 欧美日一区二区三区在线观看国产免 | 精品中文在线| 精品在线网站观看| 福利一区和二区| 成人黄色av| 日韩精品免费一区二区在线观看| 久久久久一区| 午夜欧美精品| 中文字幕日韩欧美精品高清在线| 亚洲三级网址| 国产精品中文字幕制服诱惑| 麻豆久久一区| 成人精品视频| 国产综合精品| 蜜桃视频免费观看一区| 日韩精品视频一区二区三区| 国产精品www994| 成人在线视频免费| 欧美午夜精彩| 丝袜美腿成人在线| 国产午夜久久av| 国产成人精品免费视| 香蕉成人av| 99精品视频在线| 中文字幕免费精品| 国产精品66| 一本大道色婷婷在线| 欧美日韩三区| 青青草国产成人99久久| 免费精品一区| 久久久噜噜噜| 日韩 欧美一区二区三区| 国产精品黄网站| 久久精品官网| 三级久久三级久久久| 久久久久观看| 影音先锋国产精品| 97成人超碰| 国产精品久久久久av电视剧| 在线日韩成人| 日本激情一区| 天堂va蜜桃一区二区三区| 久久国内精品视频| 蜜桃精品在线| 午夜天堂精品久久久久| 精品久久在线| 国产亚洲毛片| 国产中文字幕一区二区三区| 女主播福利一区| 国产精品成人自拍| 伊人成人网在线看| 麻豆国产欧美日韩综合精品二区| 国产一区久久| 国产精品亚洲人成在99www| 神马午夜久久| 国产亚洲高清在线观看| 影视先锋久久| 久久亚洲电影| 97精品视频在线看| 亚洲精品在线国产| 久久久久久久久久久妇女| 国产亚洲久久| 一区在线免费| 高清av一区| 日韩欧美另类中文字幕| 韩国精品主播一区二区在线观看| 欧美中文一区| 欧美另类综合| 国产欧洲在线| 国产精品午夜一区二区三区| 香蕉国产精品| 国产一区调教| 亚洲色图国产| 久久理论电影| 国产一区国产二区国产三区 | 色狠狠一区二区三区| 99久久亚洲精品| 久久99精品久久久野外观看| 久久国产福利| 999久久久亚洲| 精品一区二区三区免费看| 亚州精品视频| 在线综合亚洲| 久久国产中文字幕| 精品亚洲精品| 亚洲精品中文字幕99999| 女人av一区| 日本欧美不卡| 国产高潮在线| 麻豆国产精品| 国产亚洲欧美日韩精品一区二区三区 | 欧美日韩中文一区二区| 国产一区丝袜| 免费在线播放第一区高清av| 日韩国产一区二| 精品国模一区二区三区| 电影91久久久| 久久久久伊人| 国产精品一国产精品k频道56| 日韩在线黄色| 亚洲免费观看高清完整版在线观| 五月婷婷亚洲| 激情五月色综合国产精品| 久久精品成人| 99久久久久久中文字幕一区| 最近高清中文在线字幕在线观看1| 久久av日韩| 麻豆极品一区二区三区| 国产精品videossex| 欧美久久亚洲| 亚洲精品系列| 亚久久调教视频| 亚洲人成亚洲精品| 亚洲精品少妇| 亚洲日本国产| 日本一区中文字幕| 中文字幕av一区二区三区四区| 亚洲欧美日韩在线观看a三区| 夜夜嗨一区二区| 亚洲免费在线| 水野朝阳av一区二区三区| 三级亚洲高清视频| 热久久久久久久| 日本在线不卡视频| 欧美日韩亚洲一区二区三区在线| 国产高清久久| 亚洲一区亚洲| 蜜臀av亚洲一区中文字幕| 蜜桃91丨九色丨蝌蚪91桃色| 中文字幕亚洲在线观看| 日韩av字幕| 国产精品麻豆成人av电影艾秋| 久久gogo国模啪啪裸体| 国产不卡av一区二区| 热三久草你在线| 亚洲香蕉网站| 老司机久久99久久精品播放免费| 亚洲ww精品| 国产精品成人3p一区二区三区| 久久久久久久久成人| 精品国产日韩欧美精品国产欧美日韩一区二区三区 | 日本精品在线播放| 国产精品免费精品自在线观看| 国产欧美另类| 亚洲三级网址| 国产精品欧美三级在线观看| 国产成人77亚洲精品www| 日韩成人高清| 亚洲神马久久| 日本中文字幕一区二区| 国产精品xxx| 日韩中文欧美| 免费看的黄色欧美网站| 日韩激情啪啪| 亚洲深夜视频| 麻豆亚洲精品| 国产精品va| 国产91久久精品一区二区| 天堂成人免费av电影一区| 亚洲精品一级| 国产成人精品免费视| 欧美日韩国产探花| 久久国产麻豆精品| 亚洲www啪成人一区二区| 丝袜a∨在线一区二区三区不卡| 欧美有码在线| 蜜桃精品在线| 日韩精品免费视频一区二区三区| 精品国产中文字幕第一页| 极品日韩av| 久久精品xxxxx| 久久精品av| 欧美伊人影院| 亚洲调教视频在线观看| 日韩精品电影一区亚洲| 精品久久中文| 国产精品毛片一区二区三区| 国产欧美午夜| 免费不卡中文字幕在线| 国产日韩欧美一区二区三区| 久久中文字幕二区| 国产精品久久久久久模特| 视频一区中文| 久久精品国产在热久久| 亚洲欧美日韩国产一区| 国产一区2区| 日韩一区精品| 久久影视一区| 久久影院资源站| 亚洲一区二区三区高清| 久久精品免视看国产成人| 蜜桃av一区二区三区电影| 一区二区精品伦理...| 日本aⅴ亚洲精品中文乱码| 久久免费大视频| 精品中文在线| 天堂久久一区| 激情五月色综合国产精品|