Google 2017 I/O開發(fā)者大會于近日召開,在開發(fā)者大會上谷歌除了發(fā)布了Android O等一些新產(chǎn)品之外葱蝗,也對Android代碼的架構(gòu)做出了一個官方的回應(yīng)立磁。
Google 2017 I/O開發(fā)者大會Android架構(gòu)組件介紹現(xiàn)場視頻
下面是官方提供的Android App開發(fā)的架構(gòu)圖:
從上圖可以看到一些關(guān)鍵字:ViewModel
,LiveData
,Room
等颂翼。其實看了上面視頻的會發(fā)現(xiàn)Google官方Android架構(gòu)組件一共包括以下幾個:
- LifeCycle : 與Activity和Fragment的生命周期有關(guān)
- LiveData :異步可訂閱數(shù)據(jù)晃洒,也是生命周期感知
- ViewModel :視圖數(shù)據(jù)持有模型,也是生命周期感知
- Room :SQLite抽象層朦乏,用于簡化SQLite數(shù)據(jù)存儲
這篇文章主要講解LifeCycle在項目的簡單用法球及。
AS中添加依賴
首先在工程根目錄的build.gradle
中添加一下內(nèi)容:
allprojects {
repositories {
jcenter()
maven { url 'https://maven.google.com' } //添加此行
}
}
然后在應(yīng)用目錄下的build.gradle
中添加以下依賴:
//For Lifecycles, LiveData, and ViewModel
compile "android.arch.lifecycle:runtime:1.0.0-alpha1"
compile "android.arch.lifecycle:extensions:1.0.0-alpha1"
annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha1"
//For Room
compile "android.arch.persistence.room:runtime:1.0.0-alpha1"
annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1"
LifeCycle相關(guān)使用
在我們平時的項目中經(jīng)常會遇到很多需要依賴生命周期的邏輯處理,比如有這么一個需求呻疹。
在某個Activity我們需要在屏幕上展現(xiàn)用戶的地理位置吃引。簡單的實現(xiàn)方法如下:
class MyLocationListener {
public MyLocationListener(Context context, Callback callback) {
// ...
}
void start() {
// connect to system location service
}
void stop() {
// disconnect from system location service
}
}
class MyActivity extends AppCompatActivity {
private MyLocationListener myLocationListener;
public void onCreate(...) {
myLocationListener = new MyLocationListener(this, (location) -> {
// update UI
});
}
public void onStart() {
super.onStart();
myLocationListener.start();
}
public void onStop() {
super.onStop();
myLocationListener.stop();
}
}
雖然以上代碼看起來很簡潔,但在實際項目中的onStart,onStop方法可能會變得相當(dāng)龐大镊尺。
此外朦佩,實際情況可能并不像上面這么簡單,例如我們需要在start位置監(jiān)聽前做用戶狀態(tài)檢測庐氮,檢測是一個耗時的任務(wù)语稠,那么很有可能在檢測結(jié)束前用戶提前退出了Activity,這時候就會導(dǎo)致myLocationListener.start()
在myLocationListener.stop()
后面調(diào)用弄砍,從而引起很多難以定位的問題仙畦。代碼如下:
class MyActivity extends AppCompatActivity {
private MyLocationListener myLocationListener;
public void onCreate(...) {
myLocationListener = new MyLocationListener(this, location -> {
// update UI
});
}
public void onStart() {
super.onStart();
Util.checkUserStatus(result -> {
// what if this callback is invoked AFTER activity is stopped?
if (result) {
myLocationListener.start();
}
});
}
public void onStop() {
super.onStop();
myLocationListener.stop();
}
}
這時候就該今天的主角LifeCycle
出場了。它提供了一套接口幫助你處理這些問題音婶。
LifeCycle
LifeCyle
類持有Activity或者Fragment的生命周期相關(guān)信息慨畸,并且支持其他對象監(jiān)聽這些狀態(tài)。
LifeCyle
有兩個枚舉用于追蹤生命周期中的狀態(tài)衣式。
Event
這是生命周期的事件類寸士,會在Framework和LifeCycle間傳遞,這些事件映射到Activity和Fragment的回調(diào)事件中碴卧。
State
LifeCycle所持有Activity或Fragment的當(dāng)前狀態(tài)弱卡。
一個類想要監(jiān)聽LifeCycle的狀態(tài),只需要給其方法加上注解:
public class MyObserver implements LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume() {
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onPause() {
}
}
aLifecycleOwner.getLifecycle().addObserver(new MyObserver());
LifeCycleOwner
LifeCycleOwner
是一個只有一個方法的接口用于表明其有一個LifeCycle對象螟深。這個方法為getLifecycle()
谐宙。
這個對象給Acitivity,F(xiàn)ragment和LifeCycle提供了一個很好的抽象關(guān)系界弧,Activity和Fragment只要實現(xiàn)這個接口就能配合LifeCycle實現(xiàn)生命周期監(jiān)聽。
注意:由于目前LifeCycle處于alpha階段搭综,所以Fragment和AppCompatActivity并不會實現(xiàn)這些方法垢箕,在此之前,可以使用
LifecycleActivity
和LifecycleFragment
兑巾。等LifeCycle趨于穩(wěn)定后条获,F(xiàn)ragment和AppCompatActivity會默認(rèn)實現(xiàn)這些。
對于之前的位置監(jiān)聽的例子蒋歌,我們可以讓MyLocationListener
繼承LifecycleObserver帅掘,在onCreate中使用LifeCycle進(jìn)行初始化,剩下的問題則不必?fù)?dān)心了堂油。因為MyLocationListener
有能力進(jìn)行生命周期的判斷修档。
class MyActivity extends LifecycleActivity {
private MyLocationListener myLocationListener;
public void onCreate(...) {
//此處進(jìn)行初始化getLifecycle()傳入LifeCycle對象
myLocationListener = new MyLocationListener(this, getLifecycle(), location -> {
// update UI
});
//檢測用戶狀態(tài)并啟用監(jiān)聽
Util.checkUserStatus(result -> {
if (result) {
myLocationListener.enable();
}
});
}
}
下面看一下MyLocationListener
class MyLocationListener implements LifecycleObserver {
private boolean enabled = false;
public MyLocationListener(Context context, Lifecycle lifecycle, Callback callback) {
...
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
void start() {
if (enabled) {
// connect
}
}
public void enable() {
enabled = true;
//?
if (lifecycle.getState().isAtLeast(STARTED)) {
// connect if not connected
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void stop() {
// disconnect if connected
}
}
LifeCycle最重要的特性就是在?處,他可以提供主動查詢生命周期狀態(tài)的方法府框。這樣就避免了上面遇到的myLocationListener.start()
在myLocationListener.stop()
后面調(diào)用的問題吱窝。
通過以上的實現(xiàn),我們的LocationListener
是完全的生命周期感知了,它可以進(jìn)行自己的初始化和資源清理而不必受Activity或者Fragment的管理院峡。這時候如果我們在其他Activity或者Fragment中使用LocationListener
兴使,我們只需要初始化它就行了,不必再擔(dān)心生命周期對它的影響照激,因為它內(nèi)部會做好這一切发魄。
通過LefeCycle工作的類我們稱之為生命周期感知
。鼓勵需要使用Android生命周期的類的庫提供生命周期感知組件俩垃,以便客戶端可以輕松地在客戶端上集成這些類励幼,而無需手動生命周期管理。
LiveData
就是生命周期感知組件的示例吆寨,將LiveData和ViewModel一起使用赏淌,可以在遵循Android生命周期的情況下,更容易的使用數(shù)據(jù)來填充UI啄清。
生命周期的最佳實踐
- 保持你的UI(Activity和Fragment)盡可能簡潔六水。它們不應(yīng)該試圖獲取它們的數(shù)據(jù)而是使用ViewModel來執(zhí)行此操作,并通過LiveData的回調(diào)將數(shù)據(jù)更新到UI中辣卒。
- 嘗試編寫數(shù)據(jù)驅(qū)動的UI掷贾,你的UI的責(zé)任是在數(shù)據(jù)更改時更新視圖,或?qū)⒂脩舨僮魍ㄖoViewModel荣茫。
- 將你的數(shù)據(jù)邏輯放在ViewModel類中想帅。 ViewModel應(yīng)該作為UI和其他數(shù)據(jù)操作的連接器。值得注意的是啡莉,ViewModel并不負(fù)責(zé)提取數(shù)據(jù)(例如港准,從網(wǎng)絡(luò))。相反咧欣,ViewModel應(yīng)該調(diào)用其他接口來執(zhí)行此工作浅缸,然后將結(jié)果提供給UI。
- 使用
Data Binding
可以讓你的的UI代碼變得相當(dāng)干凈利落魄咕。這將使你的UI更具聲明性衩椒,并最大限度地減少書寫UI更新的代碼。如果您更喜歡在Java中執(zhí)行此操作哮兰,請使用像Butter Knife
這樣的庫來避免使用樣板代碼并進(jìn)行更好的抽象毛萌。 - 如果你有一個復(fù)雜的UI,請考慮創(chuàng)建一個Presenter類來處理UI修改喝滞。這通常是過度架構(gòu)的阁将,但可能有助于使你的UI更容易測試。
- 不要在ViewModel中引用View或Activity上下文囤躁。如果ViewModel在Activity或View銷毀的情況下依舊存活冀痕,這時將導(dǎo)致內(nèi)存泄漏荔睹。
補(bǔ)充
在自定義的Activity或Fragment中實現(xiàn)LifeCycleOwner,可以實現(xiàn)LifecycleRegistryOwner
這個接口言蛇。而不是繼承(LifeCycleFragment和LifeCycleActivity)
public class MyFragment extends Fragment implements LifecycleRegistryOwner {
LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);
@Override
public LifecycleRegistry getLifecycle() {
return lifecycleRegistry;
}
}
如果你要在自定義的類中實現(xiàn)LifeCycleOwner僻他,可以使用LifecycleRegistry
,但是你需要主動向其轉(zhuǎn)發(fā)生命周期的事件。但如果你自定義類是Fragment和Activity的話并且它們實現(xiàn)的是LifecycleRegistryOwner腊尚,那么事件轉(zhuǎn)發(fā)都是自動完成的吨拗。