日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

android mvvm livedata_再谈Android应用架构——Jetpack VS 生命周期

發(fā)布時(shí)間:2025/4/16 Android 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android mvvm livedata_再谈Android应用架构——Jetpack VS 生命周期 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前面我們對(duì)MVC、MVP、MVVM進(jìn)行了詳盡的分析,但還有一個(gè)問(wèn)題懸而未決,那就是生命周期。在Android平臺(tái)上生命周期具有十分重要的意義,因此這也是架構(gòu)必須考慮的因素之一。生命周期處理不好很容易發(fā)生內(nèi)存泄漏,但對(duì)架構(gòu)而言,真正困擾我們的卻不是內(nèi)存泄漏的問(wèn)題,反而是因生命周期太短,實(shí)例被銷(xiāo)毀重建,從而產(chǎn)生一系列不必要的行為。這種情況發(fā)生的場(chǎng)景主要在屏幕旋轉(zhuǎn)以及頁(yè)面被系統(tǒng)回收時(shí)。

Activity難免需要依賴(lài)網(wǎng)絡(luò)、數(shù)據(jù)庫(kù)等數(shù)據(jù)來(lái)渲染頁(yè)面,當(dāng)屏幕旋轉(zhuǎn)時(shí),Activity重建,因而數(shù)據(jù)需要重新加載,但這完全沒(méi)有必要。一種策略是對(duì)數(shù)據(jù)進(jìn)行緩存,這是一種可考慮的方案,但它只解決了一半的問(wèn)題,如果Activity重建發(fā)生在數(shù)據(jù)返回前,此時(shí)根本來(lái)不及緩存,下一次請(qǐng)求就迅速地發(fā)生了。

在MVP、MVVM架構(gòu)中,數(shù)據(jù)由M來(lái)提供,但真正和生命周期打交道的是P和VM,我們得從這里著手解決生命周期的問(wèn)題。再明確地說(shuō)一遍,我們要解決的問(wèn)題是不論在數(shù)據(jù)返回前還是返回后,在屏幕旋轉(zhuǎn)這種場(chǎng)景下都不需要多次加載數(shù)據(jù)。這個(gè)問(wèn)題由兩種狀態(tài)組成:加載中和加載完成后,對(duì)于前者我們要知道當(dāng)前正在加載數(shù)據(jù),對(duì)于后者則只需要把數(shù)據(jù)緩存起來(lái)即可。

對(duì)數(shù)據(jù)緩存很簡(jiǎn)單,但加載中的狀態(tài)就要好好斟酌一番了,我們可以輕易地給這個(gè)狀態(tài)加標(biāo)記,但隨著重建這個(gè)標(biāo)記也會(huì)被回收,由此可以想到兩種應(yīng)對(duì)之法,一是讓P和VM不被回收,這樣就可以進(jìn)行標(biāo)記了,二是讓當(dāng)前這個(gè)加載不被回收,也就是其生命周期不和P與VM同步。不讓P和VM回收,有以下幾種方式:

  • 配置android:configChanges="orientation|keyboardHidden|screenSize"

  • onRetainCustomNonConfigurationInstance()/getLastCustomNonConfigurationInstance()

  • 繼承Fragment

除了配置configChanges,其余兩種方式都是不錯(cuò)的解決辦法。除此之外還有一種方式可以同時(shí)實(shí)現(xiàn)我們說(shuō)的兩種應(yīng)對(duì)之法,這就是Loader。關(guān)于什么是Loader以及Loader如何保持P和VM不被回收,大家可以自行查閱相關(guān)資料,如何保持一個(gè)加載任務(wù)不被回收,可以參閱architecture-samples(https://github.com/android/architecture-samples),并切換到分支deprecated-todo-mvp-loaders。

我們不打算大刀闊斧地講述每個(gè)方案的細(xì)節(jié)和優(yōu)缺點(diǎn),因?yàn)殡S著Jetpack誕生,這種復(fù)雜又費(fèi)力的方案系統(tǒng)已經(jīng)幫我們完成了,我們只需要了解系統(tǒng)是如何處理的即可。從書(shū)寫(xiě)代碼變成查看代碼,可以說(shuō)大大減少了我們對(duì)生命周期的“怨恨”,不得不說(shuō)Google這波操作很圈粉呢。在這里,我們只關(guān)注Lifecycle、ViewModel和LiveData三部分。

Lifecycle

生命周期讓人困擾的很大一部分原因是只有Activity這樣的系統(tǒng)組件才可以感知生命周期的變化,而Lifecycle的出現(xiàn)則把這種感知力放大到了任何類(lèi)。Lifecycle的原理很簡(jiǎn)單,當(dāng)生命周期變化時(shí),Activity通知到Lifecycle,其他類(lèi)就可以通過(guò)Lifecycle感知生命周期的變化了。

Lifecycle的核心就三個(gè)類(lèi):LifecycleLifecycleOwnerLifecycleObserver。從名字就可以輕易看出這是一個(gè)觀察者模式,Activity作為L(zhǎng)ifecycleOwner,把生命周期的變化反映到Lifecycle,Lifecycle再通知給所有的LifecycleObserver即可。這個(gè)概念太簡(jiǎn)單了,就不在此贅述源碼了(看了一下沒(méi)有什么亮點(diǎn)~),不過(guò)如果你感興趣,請(qǐng)注意一下ReportFragment這個(gè)類(lèi),Activity的生命周期就是通過(guò)它來(lái)通知Lifecycle的(添加一個(gè)看不見(jiàn)的Fragment,這個(gè)操作似乎似曾相識(shí)?)。

Lifecycle只是讓P和VM獲得了生命周期感知能力,并沒(méi)有解決如何保持的問(wèn)題,不過(guò)它是我們后面內(nèi)容的基礎(chǔ),所以還是很有必要了解一番。

ViewModel

這個(gè)ViewModel其實(shí)就是MVVM中的VM,但經(jīng)過(guò)Google的加工之后具備了很好的生命周期感知能力,這就是我們苦苦追尋的東西呀。現(xiàn)在我們就對(duì)它抽絲剝繭,看看系統(tǒng)是如何完成這件事的。

ViewModel的使用非常簡(jiǎn)單,就是一句話:

class?LoginActivity?:?AppCompatActivity()?{

????private?lateinit?var?loginViewModel:?LoginViewModel

????override?fun?onCreate(savedInstanceState:?Bundle?)?{
????????super.onCreate(savedInstanceState)
????????//?...
????????loginViewModel?=?ViewModelProvider(this,?LoginViewModelFactory()).get(LoginViewModel::class.java)
????}
}

當(dāng)重建發(fā)生時(shí),LoginActivity、ViewModelProvider都是新的實(shí)例,但是LoginViewModel一定得是原來(lái)的實(shí)例,這說(shuō)明它在某處被緩存了起來(lái)。先看下ViewModelProvider做了什么吧:

public?ViewModelProvider(@NonNull?ViewModelStoreOwner?owner,?@NonNull?Factory?factory)?{
????this(owner.getViewModelStore(),?factory);
}

public??T?get(@NonNull?Class?modelClass)?{
????String?canonicalName?=?modelClass.getCanonicalName();//?...return?get(DEFAULT_KEY?+?":"?+?canonicalName,?modelClass);
}public??T?get(@NonNull?String?key,?@NonNull?Class?modelClass)?{
????ViewModel?viewModel?=?mViewModelStore.get(key);if?(modelClass.isInstance(viewModel))?{//?...return?(T)?viewModel;
????}?else?{//?...???
????}if?(mFactory?instanceof?KeyedFactory)?{
????????viewModel?=?((KeyedFactory)?(mFactory)).create(key,?modelClass);
????}?else?{
????????viewModel?=?(mFactory).create(modelClass);
????}
????mViewModelStore.put(key,?viewModel);return?(T)?viewModel;
}

非常簡(jiǎn)單,從Activity獲取到了一個(gè)ViewModelStore,如果里面包含了LoginViewModel就直接取出來(lái),否則新建一個(gè)并緩存到ViewModelStore里。那么ViewModelStore是什么,它是如何保持下來(lái)的?

ViewModelStore里維護(hù)了一個(gè)Map,存儲(chǔ)ViewModel實(shí)例,僅此而已。AppCompatActivity實(shí)現(xiàn)了ViewModelStoreOwner接口,里面只有一個(gè)方法getViewModelStore,它的實(shí)現(xiàn)如下:

public?ViewModelStore?getViewModelStore()?{
????if?(getApplication()?==?null)?{
????????throw?new?IllegalStateException("Your?activity?is?not?yet?attached?to?the?"
????????????????+?"Application?instance.?You?can't?request?ViewModel?before?onCreate?call.");
????}
????if?(mViewModelStore?==?null)?{
????????NonConfigurationInstances?nc?=
????????????(NonConfigurationInstances)?getLastNonConfigurationInstance();
????????if?(nc?!=?null)?{
????????????//?Restore?the?ViewModelStore?from?NonConfigurationInstances
????????????mViewModelStore?=?nc.viewModelStore;
????????}
????????if?(mViewModelStore?==?null)?{
????????????mViewModelStore?=?new?ViewModelStore();
????????}
????}
????return?mViewModelStore;
}

這里出現(xiàn)了一個(gè)getLastNonConfigurationInstance(),我們?cè)谇懊嫣徇^(guò)一個(gè)getLastCustomNonConfigurationInstance()方法,那么應(yīng)該也有一個(gè)onRetainNonConfigurationInstance()與之對(duì)應(yīng),它的實(shí)現(xiàn)如下:

public?final?Object?onRetainNonConfigurationInstance()?{
????Object?custom?=?onRetainCustomNonConfigurationInstance();

????ViewModelStore?viewModelStore?=?mViewModelStore;
????if?(viewModelStore?==?null)?{
????????//?No?one?called?getViewModelStore(),?so?see?if?there?was?an?existing
????????//?ViewModelStore?from?our?last?NonConfigurationInstance
????????NonConfigurationInstances?nc?=
????????????????(NonConfigurationInstances)?getLastNonConfigurationInstance();
????????if?(nc?!=?null)?{
????????????viewModelStore?=?nc.viewModelStore;
????????}
????}

????if?(viewModelStore?==?null?&&?custom?==?null)?{
????????return?null;
????}

????NonConfigurationInstances?nci?=?new?NonConfigurationInstances();
????nci.custom?=?custom;
????nci.viewModelStore?=?viewModelStore;
????return?nci;
}

一切都很明了了,系統(tǒng)用的是和我們一樣的方法,只是方法名稱(chēng)稍有區(qū)別而已。ViewModelStore里緩存了ViewModel實(shí)例,那么在Activity真正銷(xiāo)毀時(shí)肯定需要清空,ViewModel和ViewModelStore都提供了一個(gè)clear()方法,ViewModelStore的clear方法實(shí)現(xiàn)如下:

public?final?void?clear()?{
????for?(ViewModel?vm?:?mMap.values())?{
????????vm.clear();
????}
????mMap.clear();
}

它會(huì)調(diào)用其中每個(gè)ViewModel的clear方法使我們有機(jī)會(huì)清除一些數(shù)據(jù)或任務(wù),然后就將Map清空了。在Activity中它是這樣被調(diào)用的:

getLifecycle().addObserver(new?LifecycleEventObserver()?{
????@Overridepublic?void?onStateChanged(@NonNull?LifecycleOwner?source,
????????????@NonNull?Lifecycle.Event?event)?{
????????if?(event?==?Lifecycle.Event.ON_DESTROY)?{
????????????if?(!isChangingConfigurations())?{
????????????????getViewModelStore().clear();
????????????}
????????}
????}
});

isChangingConfigurations()用以標(biāo)識(shí)Activity執(zhí)行onDestory方法后是否準(zhǔn)備重建,只有不重建時(shí)才會(huì)清空ViewModel,所以只要在clear時(shí)清理數(shù)據(jù)和中斷任務(wù)就好了。

現(xiàn)在我們解決了ViewModel實(shí)例保持的問(wèn)題,接下來(lái)讓我們?cè)傧胂霊?yīng)該怎么解決數(shù)據(jù)重復(fù)加載的問(wèn)題。數(shù)據(jù)重復(fù)加載主要是因?yàn)橐粋€(gè)異步任務(wù)被多次調(diào)用,例如請(qǐng)求一個(gè)列表數(shù)據(jù)時(shí),如果屏幕發(fā)生旋轉(zhuǎn),以下方法會(huì)被多次調(diào)用:

fun?getUsers(){
????executor.execute?{
????????val?users?=?model.getUsers()
????????handler.post{
????????????view?.getUsers(users)
????????}
????}
}

按照之前的說(shuō)法,可以給加載任務(wù)加上標(biāo)記,當(dāng)它正在加載中就等待它加載完成,如果已經(jīng)加載完就取緩存的數(shù)據(jù),但是這太復(fù)雜了,稍有不慎就會(huì)出問(wèn)題。如何讓事情變得簡(jiǎn)單一些,出錯(cuò)率低一些呢?

要想避免此問(wèn)題,最好的方式是只調(diào)用一次getUsers()方法,那這個(gè)方法就不能由Activity來(lái)調(diào)用了,需要ViewModel自己調(diào)用,等它拿到結(jié)果后反過(guò)來(lái)通知Activity。這不就是MVVM嗎?現(xiàn)在我們總算明白為什么被系統(tǒng)實(shí)現(xiàn)的這個(gè)類(lèi)叫ViewModel了,因?yàn)樗褪菫镸VVM量身定制的。

關(guān)于數(shù)據(jù)反過(guò)來(lái)通知Activity這件事,也不需要擔(dān)心,因?yàn)橄到y(tǒng)照樣幫我們實(shí)現(xiàn)了,這就是LiveData。

LiveData

可觀察的數(shù)據(jù)并不是只有LiveData,但LiveData有自己獨(dú)特的本領(lǐng),它也具備生命周期感知力。LiveData只有在有效的生命周期范圍內(nèi)通知觀察者,并在生命周期結(jié)束后自動(dòng)移除觀察者,僅這一點(diǎn)就足夠讓它脫穎而出。我們可以從它的observe方法,了解它處理生命周期的大致流程。

public?void?observe(@NonNull?LifecycleOwner?owner,?@NonNull?Observer?super?T>?observer)?{
????assertMainThread("observe");
????if?(owner.getLifecycle().getCurrentState()?==?DESTROYED)?{
????????//?ignore
????????return;
????}
????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);
}

這里創(chuàng)建了一個(gè)LifecycleBoundObserver來(lái)觀察Activity的生命周期,我們看看它做了哪些工作吧:

class?LifecycleBoundObserver?extends?ObserverWrapper?implements?LifecycleEventObserver?{
????//?...

????@Override
????boolean?shouldBeActive()?{
????????return?mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
????}

????@Override
????public?void?onStateChanged(@NonNull?LifecycleOwner?source,
????????@NonNull?Lifecycle.Event?event)?{
????????if?(mOwner.getLifecycle().getCurrentState()?==?DESTROYED)?{
????????????removeObserver(mObserver);
????????????return;
????????}
????????activeStateChanged(shouldBeActive());
????}

????//?...
}

它實(shí)現(xiàn)了LifecycleEventObserver,并在DESTROYED狀態(tài)時(shí)移除了觀察者,其后只是調(diào)用了一個(gè)activeStateChanged方法,這個(gè)方法實(shí)現(xiàn)如下:

void?activeStateChanged(boolean?newActive)?{
????if?(newActive?==?mActive)?{
????????return;
????}
????//?immediately?set?active?state,?so?we'd?never?dispatch?anything?to?inactive
????//?owner
????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();
????}
????if?(mActive)?{
????????dispatchingValue(this);
????}
}

這里通過(guò)是否active來(lái)分發(fā)數(shù)據(jù),在dispatchingValue中會(huì)通知所有的觀察者。

LiveData實(shí)際上是一個(gè)雙層的觀察者模式,它通過(guò)觀察Lifecycle得知是否active,在此充當(dāng)?shù)氖怯^察者。當(dāng)它的值發(fā)生變化或者監(jiān)聽(tīng)到Lifecycle變化時(shí)再通知到它的觀察者,在此又充當(dāng)被觀察者。如此它就具備了我們想要的一切能力。

總結(jié)

現(xiàn)在我們的架構(gòu)“本地化”工作又前進(jìn)了一大步,它終于在生命周期方面也不存在問(wèn)題了,使用Lifecycle+ViewModel+LiveData組合,解決了架構(gòu)最棘手的問(wèn)題,也把MVVM推向了另一個(gè)高度。當(dāng)然這并不代表著MVP就徹底敗下陣來(lái),畢竟生命周期問(wèn)題只影響了初始化時(shí)的數(shù)據(jù),大量場(chǎng)景下還是有無(wú)數(shù)的交互行為,需要根據(jù)用戶(hù)的操作主動(dòng)加載各種各樣的數(shù)據(jù),這種情況下,MVP的直觀性要遠(yuǎn)遠(yuǎn)強(qiáng)于MVVM,這個(gè)特點(diǎn)也可以簡(jiǎn)單理解為MVP適合復(fù)雜交互場(chǎng)景,MVVM適合展示型場(chǎng)景。因此我們應(yīng)該根據(jù)具體場(chǎng)景靈活選用MVP和MVVM,甚至在某些情況下可以合二為一。

還是那句話,沒(méi)有最好的架構(gòu),只有最適合當(dāng)前場(chǎng)景的架構(gòu)。

往期精彩

回顧

Git實(shí)用指南完結(jié)篇

排序算法(一)

Java集合源碼分析之Map(四):HashMap

也談Android應(yīng)用架構(gòu)

更多文章正在火速連載中,感謝您的關(guān)注!

掃描一下二維碼就可以關(guān)注哦

總結(jié)

以上是生活随笔為你收集整理的android mvvm livedata_再谈Android应用架构——Jetpack VS 生命周期的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。