Android Architecture Components 是一個(gè)由Google官方推出的庫(kù)脱惰,它能夠幫助你去構(gòu)建一個(gè)健壯搏嗡,易測(cè),可維護(hù)的應(yīng)用拉一。用于管理UI組件生命周期以及處理數(shù)據(jù)持久性等問題采盒。
架構(gòu)原則
應(yīng)用中的關(guān)注點(diǎn)分離。
Activity或Fragment內(nèi)只處理UI相關(guān)邏輯蔚润,任何與此無(wú)關(guān)的代碼都不該堆在其內(nèi)磅氨。
也就是類的單一職責(zé)化。盡可能保持精簡(jiǎn)可以避免許多生命周期相關(guān)的問題嫡纠》匙猓基于用戶交互或其他因素(如低內(nèi)存),Android系統(tǒng)可能隨時(shí)銷毀它們除盏。最好盡量減少對(duì)它們的依賴叉橱,以提供好的用戶體驗(yàn)。
數(shù)據(jù)模型驅(qū)動(dòng) UI
做到數(shù)據(jù)持久化者蠕,這樣至少有兩個(gè)好處:
1.用戶不會(huì)因?yàn)橄到y(tǒng)銷毀我們的應(yīng)用而導(dǎo)致丟失數(shù)據(jù)窃祝。
2.我們的應(yīng)用可以在網(wǎng)絡(luò)狀況不好甚至斷網(wǎng)的情況下繼續(xù)工作。
主要模塊
包含Lifecycles, LiveData, ViewModel, Room, and Paging.
下面主要講解一下Lifecycles,LiveData以及ViewModel
Lifecycles
在 android.arch.lifecycle 包中提供了可以構(gòu)建生命周期感知的組件的類和接口踱侣,這些組件可以根據(jù) Activity/Fragment 的生命周期自動(dòng)調(diào)整它的行為粪小。
從圖中我們可以看到 LifecycleOwner 是 Lifecycle 的持有者大磺,通常是一個(gè) Activity 或 Fragment。想要獲取 Lifecycle 只能通過 LifecycleOwner 的 getLifecycle 方法探膊。Lifecycle 是可觀察的杠愧,它可以持有多個(gè) LifecycleObserver。
-
Lifecycle:它是一個(gè)持有 Activity/Fragment 生命周期狀態(tài)信息的類突想,并且允許其他對(duì)象觀察此狀態(tài)殴蹄。Lifecycle 內(nèi)部維護(hù)了兩個(gè)枚舉,一叫 Event猾担,另一個(gè)叫 State袭灯。Event 是對(duì) Android 組件(Activity 或 Fragment)生命周期函數(shù)的映射,當(dāng) Android Framework 回調(diào)生命周期函數(shù)時(shí)绑嘹,Lifecycle 會(huì)檢查當(dāng)前事件和上一個(gè)事件是否一致稽荧,如果不一致,就根據(jù)當(dāng)前事件計(jì)算出當(dāng)前狀態(tài)工腋,并通知它的觀察者(LifecycleObserver)生命狀態(tài)已經(jīng)發(fā)生變化姨丈。觀察者收到通知后,通過 Lifecycle 提供的 getCurrentSate 方法來獲取剛剛 Lifecycle 計(jì)算出來的當(dāng)前狀態(tài)擅腰,觀察者根據(jù)這個(gè)狀態(tài)來決定要不要執(zhí)行某些操作
lifecycle-states.png
LifecycleOwner
-
LifecycleOwner:是一個(gè)具有單一方法的接口蟋恬。如果一個(gè)類實(shí)現(xiàn)了此接口,則該類中需要持有一個(gè)
Lifecycle
對(duì)象趁冈,并通過LifecycleOwner#getLifecycle()
方法返回該對(duì)象歼争。Support Library 26.1+ 已經(jīng)集成了此組件。
并不是只有 Activity 和 Fragment 才可以實(shí)現(xiàn) LifecycleOwner 接口的渗勘,任何和 Activity/Fragment 生命周期有關(guān)系的類都可以實(shí)現(xiàn)此接口沐绒。通過實(shí)現(xiàn)此接口,該類完全是生命周期可感知的旺坠,只需要對(duì)它進(jìn)行初始化乔遮,它就可以進(jìn)行自己的初始化和清理操作,而不受其 Activity/Fragment 的管理取刃。詳細(xì)可以參看官方文檔說明:LifecycleOwner 實(shí)踐
LifecycleObserver
可以使用 Lifecycle 的類被稱為生命周期感知組件
蹋肮。(也就是繼承實(shí)現(xiàn)LifecycleObserver 的類)。
谷歌提倡那些需要和 Android 生命周期協(xié)作的類庫(kù)提供生命周期感知組件璧疗,這樣客戶端代碼就可以很容易集成這些類庫(kù)括尸,而不需要客戶端手動(dòng)管理類庫(kù)中和 Android 生命周期相關(guān)的代碼。
class MyObserver implements LifecycleObserver {
private boolean enabled = false;
public MyObserver(Context context, Lifecycle lifecycle, Callback callback) {
...
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
void start() {
if (enabled) {
// connect
}
}
public void enable() {
enabled = true;
if (lifecycle.getCurrentState().isAtLeast(STARTED)) {
// connect if not connected
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void stop() {
// disconnect if connected
}
}
通過注解就可以監(jiān)聽對(duì)應(yīng)的生命周期事件病毡,同時(shí)別忘了調(diào)用 owner.getLifecycle().addObserver() 把觀察者(MyObserver)注冊(cè)到 Lifecycle.
LiveData
LiveData 是一個(gè) observable 數(shù)據(jù)的持有類,和普通的 observable 不同屁柏,LiveData 是生命周期感知的,意味著它代表其它應(yīng)用組件譬如 Activity、Fragment米愿、Service 的生命周期关顷。這確保了 LiveData 只會(huì)更新處于活躍狀態(tài)的組件。
LiveData 通過內(nèi)部類的形式實(shí)現(xiàn)了 LifecycleObserver实愚,它整個(gè)工作流程大概是這樣的:
- 將實(shí)現(xiàn)了 LifecycleObserver 的內(nèi)部類注冊(cè)到 owner 的 Lifecycle。
- LifecycleObserver 監(jiān)聽了 Lifecycle 所有的生命周期事件
- 當(dāng)有生命周期事件發(fā)生時(shí),檢查 Lifecycle 的狀態(tài)是否至少是
STARTED
來判斷 lifecycle 是否處于活躍狀態(tài) - 當(dāng)維護(hù)的值被改變時(shí)阵赠,如果 Lifecycle 處于活躍狀態(tài),通知觀察者(實(shí)現(xiàn)了
android.arch.lifecycle.Observer
接口的對(duì)象)肌稻,否則什么也不做 - 當(dāng) Lifecycle 從非活躍狀態(tài)恢復(fù)到活躍狀態(tài)時(shí)清蚀,檢查維護(hù)的值是否在非活躍期間有更新過,如果有爹谭,通知觀察者
- 當(dāng) Lifecycle 處于完結(jié)狀態(tài)
DESTROYED
時(shí)枷邪,從 Lifecycle 中移除 LifecycleObserver。
很顯然诺凡,LiveData 是響應(yīng)式的东揣,令人驚艷的是,它有效解決了后臺(tái)回調(diào)和 Android 生命周期的上古謎題腹泌。
LiveData 使用起來是這樣的:
public class NameViewModel extends ViewModel {
// Create a LiveData with a String
private MutableLiveData<String> mCurrentName;
public MutableLiveData<String> getCurrentName() {
if (mCurrentName == null) {
mCurrentName = new MutableLiveData<String>();
}
return mCurrentName;
}
// Rest of the ViewModel...
}
現(xiàn)在嘶卧,Activity 可以訪問這個(gè)列表如下:
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
model.getUsers().observe(this, users -> {
// update UI
});
}
}
它還提供了 Transformations 來幫助我們轉(zhuǎn)換 LiveData 所持有的數(shù)據(jù)。
Transformations.map()
在LiveData數(shù)據(jù)的改變傳遞到觀察者之前凉袱,在數(shù)據(jù)上應(yīng)用一個(gè)方法:
LiveData<User> userLiveData = ...;
LiveData<String> userName = Transformations.map(userLiveData, user -> {
user.name + " " + user.lastName
});
Transformations.switchMap()
與Transformations.map()類似芥吟,只不過這里傳遞個(gè)switchMap()的方法必須返回一個(gè)LiveData對(duì)象。
private LiveData<User> getUser(String id) {
...;
}
LiveData<String> userId = ...;
LiveData<User> user = Transformations.switchMap(userId, id -> getUser(id) );
ViewModel
看到 ViewModel 這個(gè)詞绑蔫,就會(huì)讓人想起 MVVM运沦,ViewModel 正是 MVVM 架構(gòu)里面的一個(gè)重要角色。
MVVM 按職責(zé)把類分為三種角色配深,分別是 View携添,ViewModel,Model篓叶。ViewModel 正好處于中間烈掠,是連接 View 和 Model 的橋梁。
- View 只做兩件事情缸托,一件是根據(jù) ViewModel 中存儲(chǔ)的狀態(tài)渲染界面左敌,另外一件是將用戶操作轉(zhuǎn)發(fā)給 ViewModel。用一個(gè)公式來表述是這樣的:
view = render(state) + handle(event)
俐镐。 - ViewModel 也只做兩件事矫限。一方面提供 observable properties 給 View 觀察,一方面提供 functions 給 View 調(diào)用,通常會(huì)導(dǎo)致 observable properties 的改變叼风,以及帶來一些額外狀態(tài)取董。observable properties 是指 LiveData、Observable(RxJava) 這種可觀察屬性无宿。View 正是訂閱了這些屬性茵汰,實(shí)現(xiàn)模型驅(qū)動(dòng)視圖。functions 是指可以用來響應(yīng)用戶操作的方法或其它對(duì)象孽鸡,ViewModel 不會(huì)也不應(yīng)該自己處理業(yè)務(wù)蹂午,它通過 functions 把業(yè)務(wù)邏輯的處理委派給 Model。用一個(gè)公式來表述是這樣的:
viewmodel = observable properties + functions
彬碱。 - Model 是整個(gè)應(yīng)用的核心豆胸。它包含數(shù)據(jù)以及業(yè)務(wù)邏輯,網(wǎng)絡(luò)訪問堡妒、數(shù)據(jù)持久化都是它的職責(zé)配乱。用一個(gè)公式來表述是這樣的:
model = data + state + business logic
。
在 Android 中皮迟,View 包含 Activity 和 Fragment搬泥,由于 Activity 和 Fragment 可以銷毀后重建,因此要求 ViewModel 在這個(gè)過程中能夠存活下來伏尼,并綁定到新的 Activity 或 Fragment忿檩。架構(gòu)組件提供了 ViewModel 來幫我們實(shí)現(xiàn)這點(diǎn)。
ViewModel的生命周期跟著傳遞給ViewModelProvider的LifeCycle走爆阶,當(dāng)生成了ViewModel的實(shí)例后燥透,它會(huì)一直待在內(nèi)存中,直到對(duì)應(yīng)的LifeCycle徹底結(jié)束辨图。下面是ViewModel與Activity對(duì)應(yīng)的生命周期圖:
ViewModel將數(shù)據(jù)從UI中分離出來班套。并且當(dāng)Activity或Fragment重構(gòu)的時(shí)候,ViewModel會(huì)自動(dòng)保留之前的數(shù)據(jù)并給新的Activity或Fragment使用故河。
public class MyViewModel extends ViewModel {
private MutableLiveData<List<User>> users;
public LiveData<List<User>> getUsers() {
if (users == null) {
users = new MutableLiveData<List<Users>>();
loadUsers();
}
return users;
}
private void loadUsers() {
// Do an asynchronous operation to fetch users.
}
}
接著在我們的Activity中就能這樣使用了:
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
// Create a ViewModel the first time the system calls an activity's onCreate() method.
// Re-created activities receive the same MyViewModel instance created by the first activity.
MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
model.getUsers().observe(this, users -> {
// update UI
});
}
}
當(dāng) Activity 或 Fragment 真正 finish 的時(shí)候吱韭,框架會(huì)調(diào)用 ViewModel 中的 onCleared
方法,在這個(gè)方法里面清除不再使用的資源鱼的。
如果
ViewModel
需要Application
上下文理盆,例如查找系統(tǒng)服務(wù),則可以擴(kuò)展AndroidViewModel
該類并在構(gòu)造函數(shù)中接收Application
凑阶。
Fragment之間的數(shù)據(jù)共享
在Activity中包好多個(gè)Fragment并且需要相互通信是非常常見的猿规,這時(shí)就需要這些Fragment定義一些接口,然后讓Activity來進(jìn)行協(xié)調(diào)宙橱。
上面這個(gè)問題可以被ViewModel輕易解決姨俩,假設(shè)有這么一個(gè)Activity蘸拔,它包含F(xiàn)ragmentA和FragmentB,其中A是用戶列表哼勇,B是用戶的詳細(xì)數(shù)據(jù)都伪,點(diǎn)擊列表上的某個(gè)用戶,在B中顯示相應(yīng)的數(shù)據(jù)积担。如以下示例代碼所示:
public class SharedViewModel extends ViewModel {
private final MutableLiveData<Item> selected = new MutableLiveData<Item>();
public void select(Item item) {
selected.setValue(item);
}
public LiveData<Item> getSelected() {
return selected;
}
}
public class MasterFragment extends Fragment {
private SharedViewModel model;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
itemSelector.setOnClickListener(item -> {
model.select(item);
});
}
}
public class DetailFragment extends Fragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
model.getSelected().observe(this, { item ->
// Update the UI.
});
}
}
這里要注意的是兩個(gè)Fragment都使用了getActivity作為參數(shù)來獲得ViewModel實(shí)例。這表示這兩個(gè)Fragment獲得的ViewModel對(duì)象是同一個(gè)SharedViewModel猬仁。
使用了ViewModel的好處如下:
Activity不需要做任何事情帝璧,不需要干涉這兩個(gè)Fragment之間的通信。
Fragment不需要互相知道湿刽,即使一個(gè)消失不可見的烁,另一個(gè)也能很好的工作。
Fragment有自己的生命周期诈闺,它們之間互不干擾渴庆,即便你用一個(gè)FragmentC替代了B,F(xiàn)ragmentA也能正常工作雅镊,沒有任何問題襟雷。
參考:
https://developer.android.com/topic/libraries/architecture/guide.html
https://developer.android.com/topic/libraries/architecture/lifecycle.html
https://developer.android.com/topic/libraries/architecture/livedata.html
https://developer.android.com/topic/libraries/architecture/viewmodel.html
https://listenzz.github.io/android-lifecyle-works-perfectly-with-rxjava.html
http://www.cnblogs.com/zqlxtt/p/6888507.html