Android 項(xiàng)目最新架構(gòu)
0.前言
為了幫助開(kāi)發(fā)著打造一款優(yōu)秀的APP,Google可謂費(fèi)盡心力,推出了各種諸如MVP,MVVM等等項(xiàng)目架構(gòu)的思路,幫助開(kāi)發(fā)者更加高效的開(kāi)發(fā),盡管這樣,Google還是接著推出了一個(gè)新的項(xiàng)目架構(gòu),以便給予開(kāi)發(fā)者更多的選擇,至于這種架構(gòu)思路和MVP等框架的優(yōu)劣,各位看完文章或許自有定論。
1、生命周期
在移動(dòng)操作系統(tǒng)上開(kāi)發(fā)軟件其實(shí)是十分復(fù)雜的一件事情,因?yàn)槲覀冸S時(shí)需要面對(duì)系統(tǒng)和用戶的各種不可預(yù)料的操作,很多時(shí)候,事情并不向著我們預(yù)設(shè)的方向方向進(jìn)展。因此系統(tǒng)向我們提供了核心組件的生命周期這種東西,告知我們的APP正處在什么樣的狀況中,以便于我們做出相應(yīng)的處理。
如上圖。雖然Google給出了Activity非常詳盡的生命周期結(jié)構(gòu),因此我們對(duì)根據(jù)生命周期做出相應(yīng)的合理的安排,比如添加和移除實(shí)時(shí)GPS位置監(jiān)聽(tīng):
可是隨著業(yè)務(wù)的逐漸復(fù)雜,我們可能在添加監(jiān)聽(tīng)之間需要向服務(wù)器驗(yàn)證某些用戶信息,等返回信息正確才去監(jiān)聽(tīng)定位。那么在網(wǎng)絡(luò)異步回調(diào)的時(shí)候,我們就很難知道當(dāng)前的activity的生命周期狀態(tài)。
如果發(fā)生上圖的情況,那么我們的占用的相關(guān)資源就可能永遠(yuǎn)無(wú)法移除了。這還只是冰山一角,大家盡可以想想,當(dāng)我們的異步調(diào)用面對(duì)無(wú)法預(yù)知的用戶操作和系統(tǒng)處理的時(shí)候,什么問(wèn)題都可能發(fā)生。
總而言之,由于我們對(duì)于UI實(shí)時(shí)的狀態(tài)做不到了如指掌,以至于對(duì)數(shù)據(jù)和邏輯的處理就無(wú)法盡善盡美。這是類似隱患得不到很好的解決根本原因。
2、Google大禮包
這次Google推出了一套新的項(xiàng)目架構(gòu)組件和架構(gòu)思路,從UI到Data,幫助我們更加精準(zhǔn)的開(kāi)發(fā)自己的APP。
2.1 核心:Lifecycle Components
這套架構(gòu)最核心的就是生命周期組件,:Lifecycle Components用于管理UI控制器(Activity/Freagment)的生命周期,方便查詢當(dāng)前組件生命周期的狀態(tài)。
可查詢的狀態(tài)如下:
具體的使用方式有兩種:
- 繼承LifecycleActivity/LifecycleFragment即可
- 自己實(shí)現(xiàn)LifecycleRegistryOwner接口
java
// 通過(guò)繼承,就已經(jīng)將自己的生命周期的交給了Lifecycle Components管理了。
public classMainActivity extends LifecycleActivity {
}
那我們?nèi)绾问褂媚兀?/span>
// 通過(guò)繼承LifecycleObserver,保證我們可以通過(guò)注解或者接口查詢UI的生命周期
public classMyTest implements LifecycleObserver {
private Lifecycle lifecycle;
// Lifecycle包含了當(dāng)前組件的生命周期
public MyTest(Lifecycle lifecycle){
lifecycle.addObserver( this);
this.lifecycle=lifecycle;
}
// 當(dāng)onResume發(fā)生的時(shí)候,該方法被調(diào)用
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public voidresume(){
Log.i( "TAG", "it called when resume ");
}
public voiddoTest( Strings){
// 隨時(shí)可以查詢當(dāng)前的UI狀態(tài)
if(lifecycle.getCurrentState().equals(Lifecycle.State.RESUMED)){
Log.i( "TAG", "resume");
} else{
Log.i( "TAG", "is not resume !! ");
}
}
}
public classMainActivity extends LifecycleActivity {
@Override
protected voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//將當(dāng)前Activity的生命周期傳遞到MyTest中即可
MyTest myTest= newMyTest( this.getLifecycle());
}
}
看到這里,你一定心頭一喜,如果有這個(gè)組件,那么我們就完全有能力將Activity作為一個(gè)UI的控制器,僅僅用來(lái)顯示UI和相應(yīng)用戶操作,把Activity的大小縮小至最小。不用著急,大禮包遠(yuǎn)不止這些。
3、ViewModel和LiveData
- ViewModel 是一個(gè)UI相關(guān)數(shù)據(jù)的暫存器,當(dāng)所有相關(guān)的UI都finish掉的時(shí)候,它才會(huì)清除自己的數(shù)據(jù)。
- LiveData則是一個(gè)持有具體數(shù)據(jù)并且可被觀察,能感知生命周期的組件(它就像RxJava中一個(gè)能遵循組件生命周期的Observable)
他倆的關(guān)系,就是,ViewModel負(fù)責(zé)管理著不同的LiveData,并把它提供給UI。
3.1 LiveData
我們可以先來(lái)說(shuō)說(shuō)LiveData。由于它已經(jīng)能夠感知生命周期,也就意味著我們并不需要在去查詢當(dāng)前UI的生命周期,由于可被觀察,也就意味著當(dāng)它持有的數(shù)據(jù)發(fā)生改變,觀察者可以立即受到信息。livedata最重要的方法是一下幾個(gè):
onActive() // 當(dāng)前LiveData有超過(guò)一個(gè)的活躍的觀察者時(shí),被調(diào)用
onInactive() // 當(dāng)前沒(méi)有任何活躍的觀察時(shí),著被調(diào)用
setValue() // 勇于改變當(dāng)前數(shù)據(jù),這樣觀察者可以受到改變后的數(shù)據(jù)。
// 觀察數(shù)據(jù)變化,并感知當(dāng)前UI的生命周期
observe(LifecycleOwner owner, Observer<T> observer)
這里有一個(gè)活躍的觀察者的概念,我們不妨把它放在后面來(lái)看。LiveData的用法如下:
publicclassLocationLiveDataextendsLiveData<Location> {
privateLocationManager locationManager;
privateSimpleLocationListener listener = newSimpleLocationListener() {
@Override
publicvoidonLocationChanged(Location location){
setValue(location);
}
};
publicLocationLiveData(Context context){
locationManager = (LocationManager) context.getSystemService(
Context.LOCATION_SERVICE);
}
@Override
protectedvoidonActive(){
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
}
@Override
protectedvoidonInactive(){
locationManager.removeUpdates(listener);
}
}
publicclassMainActivityextendsLifecycleActivity{
@Override
protectedvoidonCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LiveData<Location> myLocationListener = newLocationLiveData();
/*
* observe(LifecycleOwner owner, Observer<T> observer)
* 這個(gè)方法就是向LiveData中添加觀察者,
* LiveData則可以通過(guò)LifecycleOwner來(lái)判斷
* 當(dāng)前傳入的觀察者是否是活躍的(也就是UI是否可見(jiàn)了)
*/
myLocationListener.observe( this, newObserver<Location>() {
@Override
publicvoidonChanged(@Nullable Location location){
// update
//當(dāng)LiveData中通過(guò)setValue()修改了數(shù)據(jù)時(shí),
//這里將會(huì)受到修改后的數(shù)據(jù)
}
});
}
}
好了,LiveData基本的用法講完了,由于有了LiveData,我們的data更加“智能”了。當(dāng)UI不可見(jiàn)的時(shí)候,改變的數(shù)據(jù)將不會(huì)被更新到UI上。
而且如果數(shù)據(jù)在不同的UI界面都會(huì)被用到的時(shí)候,我們還可以一個(gè)單例的LiveData,為不同的UI提供統(tǒng)一的數(shù)據(jù)。這些操作就不去細(xì)講了。
現(xiàn)在回頭看LiveData,我們發(fā)現(xiàn)它至少有以下幾個(gè)優(yōu)點(diǎn):
- 可以避免內(nèi)存泄露:由于 Observer 和 Lifecycle 綁定,當(dāng) Lifecycle 被銷毀后,Observer 自動(dòng)被清理。
- 避免在 Activity 被銷毀后更新數(shù)據(jù)導(dǎo)致的崩潰情況
- 數(shù)據(jù)可共享
- 數(shù)據(jù)更新更智能:當(dāng)數(shù)據(jù)在UI不可見(jiàn)的時(shí)候更新了,在恢復(fù)可見(jiàn)的時(shí)候,最新的數(shù)據(jù)會(huì)及時(shí)更新到UI上。
- 不需要在Activity中額外處理生命周期事件
一顆賽艇!
3.2 ViewModel
ViewModel則相對(duì)簡(jiǎn)單些,因?yàn)樗淖饔檬菚捍鎁I相關(guān)的數(shù)據(jù),保證即使Activity配置更改,重新創(chuàng)建時(shí),數(shù)據(jù)依然能夠被保存好。
基本用法如下:
publicclassMyViewModelextendsViewModel{
// MyViewModel用于管理不同的LiveData
privateMutableLiveData<List<User>> users;
publicLiveData<List<User>> getUsers() {
if(users == null) {
users = newMutableLiveData<List<Users>>();
loadUsers();
}
returnusers;
}
privatevoidloadUsers(){
// do async operation to fetch users
}
}
publicclassMyActivityextendsAppCompatActivity{
publicvoidonCreate(Bundle savedInstanceState){
// 通過(guò)了ViewModelProviders來(lái)獲取ViewModel
// 用戶獲取和Activity綁定的ViewModel
MyViewModel model = ViewModelProviders.of( this).get(MyViewModel.class);
model.getUsers().observe( this, users -> {
// update UI
});
}
}
這是ViewModel的最基本的用法,它負(fù)責(zé)從各個(gè)地方獲取數(shù)據(jù),然后把數(shù)據(jù)裝到LiveData中,提供給UI;當(dāng)然ViewModel也可以在不同的Fragment中共享,在這里就不多講了。
由于ViewModel的本身和activity/fragment的生命周期綁定,當(dāng)與之綁定的最后一個(gè)UI 銷毀時(shí),ViewModel才會(huì)clean自身的數(shù)據(jù)。
如圖所示
4、數(shù)據(jù)持久化:Room
Room是Google提供的SQLite的ORM的解決方案,其實(shí)本質(zhì)上和其他的ORM框架沒(méi)什么特別大的差別,沒(méi)有太多新意,因此只給出大體的架構(gòu)圖,有興趣的同學(xué)可以自行去學(xué)習(xí)
5、總結(jié)
我們現(xiàn)在回頭看整個(gè)架構(gòu)
其實(shí)最有有趣的就是UI-ViewModel這個(gè)部分,這套架構(gòu)至少可以幫助我們做到一下幾點(diǎn):
- UI與Data真正分離
- 異步調(diào)用和邏輯控制可以更加精細(xì)(因?yàn)閷?duì)生命周期感知更多)
- 實(shí)現(xiàn)Model驅(qū)動(dòng)UI
6、勘誤
暫無(wú)
附錄

責(zé)任編輯:售電衡衡
-
權(quán)威發(fā)布 | 新能源汽車產(chǎn)業(yè)頂層設(shè)計(jì)落地:鼓勵(lì)“光儲(chǔ)充放”,有序推進(jìn)氫燃料供給體系建設(shè)
2020-11-03新能源,汽車,產(chǎn)業(yè),設(shè)計(jì) -
中國(guó)自主研制的“人造太陽(yáng)”重力支撐設(shè)備正式啟運(yùn)
2020-09-14核聚變,ITER,核電 -
探索 | 既耗能又可供能的數(shù)據(jù)中心 打造融合型綜合能源系統(tǒng)
2020-06-16綜合能源服務(wù),新能源消納,能源互聯(lián)網(wǎng)
-
新基建助推 數(shù)據(jù)中心建設(shè)將迎爆發(fā)期
2020-06-16數(shù)據(jù)中心,能源互聯(lián)網(wǎng),電力新基建 -
泛在電力物聯(lián)網(wǎng)建設(shè)下看電網(wǎng)企業(yè)數(shù)據(jù)變現(xiàn)之路
2019-11-12泛在電力物聯(lián)網(wǎng) -
泛在電力物聯(lián)網(wǎng)建設(shè)典型實(shí)踐案例
2019-10-15泛在電力物聯(lián)網(wǎng)案例
-
新基建之充電樁“火”了 想進(jìn)這個(gè)行業(yè)要“心里有底”
2020-06-16充電樁,充電基礎(chǔ)設(shè)施,電力新基建 -
燃料電池汽車駛?cè)雽こ0傩占疫€要多久?
-
備戰(zhàn)全面電動(dòng)化 多部委及央企“定調(diào)”充電樁配套節(jié)奏
-
權(quán)威發(fā)布 | 新能源汽車產(chǎn)業(yè)頂層設(shè)計(jì)落地:鼓勵(lì)“光儲(chǔ)充放”,有序推進(jìn)氫燃料供給體系建設(shè)
2020-11-03新能源,汽車,產(chǎn)業(yè),設(shè)計(jì) -
中國(guó)自主研制的“人造太陽(yáng)”重力支撐設(shè)備正式啟運(yùn)
2020-09-14核聚變,ITER,核電 -
能源革命和電改政策紅利將長(zhǎng)期助力儲(chǔ)能行業(yè)發(fā)展
-
探索 | 既耗能又可供能的數(shù)據(jù)中心 打造融合型綜合能源系統(tǒng)
2020-06-16綜合能源服務(wù),新能源消納,能源互聯(lián)網(wǎng) -
5G新基建助力智能電網(wǎng)發(fā)展
2020-06-125G,智能電網(wǎng),配電網(wǎng) -
從智能電網(wǎng)到智能城市
-
山西省首座電力與通信共享電力鐵塔試點(diǎn)成功
-
中國(guó)電建公司公共資源交易服務(wù)平臺(tái)摘得電力創(chuàng)新大獎(jiǎng)
-
電力系統(tǒng)對(duì)UPS的技術(shù)要求