一、AAC簡介
AAC全稱Android Architecture Components,是Android官方推出的MVVM架構指導方案。Android官方之前為了支持MVVM已經推出了DataBinding方案,AAC與DataBinding之間沒有任何關系,但它們可以結合使用。
二、使用AAC需要導入如下依賴:
dependencies {
def lifecycle_version = "2.3.1"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
//非java8使用
//annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
//java8使用
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
}
三、AAC主要包含:
1、Lifecycle
Lifecycle一看就是用來管理生命周期的,它負責將Activity/Fragment的生命周期同步給其它模塊,主要飽含三種角色:
- Lifecycle:生命周期本身,其它模塊(LifecycleObserver)可以對其進行觀測,以便在狀態發生變化時接收通知,同時也可以主動從這里獲取當前狀態。
- LifecycleOwner:Lifecycle的持有者,一般為上下文對象,比如Activity和Fragment,因為生命周期就是從它們這里同步出去的。
- LifecycleObserver:生命周期觀察者,觀察者通過向Lifecycle注冊來監聽生命周期的變化。
簡單的流程如下:
Activity或Fragment實現LifecycleOwner接口,創建并持有Lifecycle對象。
某模塊實現LifecycleObserver接口,并將自身注冊到步驟1創建的Lifecycle對象中,以便觀察Activity或Fragment生命周期的變化。
生命周期變化時,Activity或Fragment將狀態同步給Lifecycle對象。
Lifecycle對象dispatch事件給所有LifecycleObserver對象。
在新版本(1.1.1以上)中,FragmentActivity和Fragment已經集成了Lifecycle,需要處理的只有流程2。
代碼如下:
UserActivity :
public class UserActivity extends FragmentActivity implements Observer<User> {
private final String TAB = "UserActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user);
getLifecycle().addObserver(new UserController(getLifecycle()));
log("onCreate");
}
@Override
protected void onStart() {
super.onStart();
log("onStart");
}
@Override
protected void onResume() {
super.onResume();
log("onResume");
}
@Override
protected void onPause() {
log("onPause");
super.onPause();
}
@Override
protected void onStop() {
log("onStop");
super.onStop();
}
@Override
protected void onDestroy() {
log("onDestroy");
super.onDestroy();
}
private void log(String msg) {
Log.i(TAB, msg);
}
@Override
public void onChanged(User user) {
}
}
UserController :
public class UserController implements LifecycleObserver {
private Lifecycle mLifecycle;
public UserController(Lifecycle lifecycle) {
this.mLifecycle = lifecycle;
}
private void log(String msg) {
Log.i("UserController", msg);
}
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
public void onCreate() {
log("onCreate");
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart() {
log("onStart");
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume() {
log("onResume");
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onPause() {
log("onPause");
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onStop() {
log("onStop");
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onDestroy() {
log("onDestroy");
}
@OnLifecycleEvent(Lifecycle.Event.ON_ANY)
public void onAny() {
log("onAny:" + mLifecycle.getCurrentState());
}
}
UserController作為控制器是為了分離出原本在UserActivity中處理的邏輯代碼,因此它需要監聽Activity的生命周期,所以它實現了LifecycleObserver。
UserActivity繼承了FragmentActivity而不是Activity是因為前者集成了Lifecycle而后者沒有,它扮演的是LifecycleOwner的角色,且是Lifecycle的創建者和持有者。
Lifecycle對象的實際類型是LifecycleRegistry。
生命周期的分發不需要關心,想了解原理的自行查看源碼,需要關心的是Observer如何接收生命周期的變化。這里使用OnLifecycleEvent注解,該注解只有一個參數,表示生命周期變化對應的事件,所有事件在代碼中都列出來了,看事件名就可以知道對應哪個生命周期了,這里不再多說。當生命周期發生變化時,Observer中對應的方法會被調用,其中ANY是比較特殊的,每次生命周期發生變化時都會在原事件觸發后觸發。
CREATE/START/RESUME事件由Owner先觸發,Observer后觸發;PAUSE/STOP/DESTROY由Observer先觸發,Owner后觸發。
UserController之后會被廢棄,因為AAC是MVVM模式的應用,后面會使用ViewModel來代替UserController。之所以本例中使用UserController,是為了排除其它干擾因素,能更直接地理解和掌握Lifecycle。
2、LiveData
2.1、LiveData是一個可被觀察的數據持有者,即它既是一個Observable(被觀察者/發布者),同時持有數據模型(或者本身作為數據模型也可以),它的Observer(觀察者)通常都是控制層對象(如Activity或Fragment)。與一般的Observable不同,LiveData能知道Observer的生命周期變化,這意味著它能同步到Activity、Fragment等組件的生命周期,這確保了LiveData只更新處于活躍狀態的Observer。
如果一個Observer的生命周期處于非DESTROYED狀態時,那么LiveData將認為這個Observer處于活躍狀態。LiveData僅通知活躍的Observer去更新UI。非活躍狀態的Observer,即使訂閱了LiveData,也不會收到更新的通知。
為了便于直觀理解,以Activity作為控制層來講解,即后面提到的Activity同時代表控制層及LiveData的觀察者。
上面提到LiveData可以觀察到Activity的生命周期變化,同時它的數據變化也能夠被Activity觀測到,因此LiveData和Activity互為觀察者。
2.2、LiveData作為觀察者時:根據前面Lifecycle所掌握到的知識,LiveData要觀察Activity就需要實現LifecycleObserver,同時將自身注冊到Activity中。
2.3、LiveData作為被觀察者時:它需要保存觀察者的集合,提供注冊和反注冊的方法。Android中已經提供了兩個LiveData相關的類,分別是LiveData和MutableLiveData,提供了作為被觀察者需要的方法,同時也提供了第1點提到的注冊自身的方法,二者的區別是前者的數據不可變,后者可變。因此,在應用LiveData時,只需要根據情況選擇繼承它們其一即可。
如沒有特別說明,LiveData指概念本身,而非具體的類。
2.4、Activity作為被觀察者時:需要實現LifecycleOwner接口,根據前面掌握的知識,實際上只需要繼承FragmentActivity即可。
2.5、Activity作為觀察者時:需要實現Observer,并注冊到LiveData中。
結合Lifecycle和LiveData在之前MVC的基礎上進行重構,代碼如下:
UserLiveData:
public class UserLiveData extends MutableLiveData<User> {
}
UserActivity:
public class UserActivity extends FragmentActivity implements Observer<User>, UserBusiness.UserListener {
private TextView mNameView;
private TextView mAgaView;
private UserBusiness mUserBusiness = UserBusiness.get();
private UserLiveData mUserLiveData;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user);
mNameView = findViewById(R.id.tv_name);
mAgaView = findViewById(R.id.tv_age);
findViewById(R.id.btn_refresh).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 向服務器請求最新用戶信息
mUserBusiness.requestUser();
}
});
// 加載數據庫緩存中的用戶信息
User user = mUserBusiness.getUser();
mUserLiveData = new UserLiveData();
// LiveData注冊對Activity的監聽,同時Activity注冊對LiveData的監聽
mUserLiveData.observe(this, this);
// 更新LiveData中的數據
mUserLiveData.postValue(user);
mUserBusiness.addListener(this);
}
@Override
protected void onDestroy() {
mUserBusiness.removeListener(this);
super.onDestroy();
}
@Override
public void onChanged(@Nullable User user) {
// LiveData中的數據更新,在這里刷新UI,這個方法是在主線程中調用的,可放心刷新UI
mNameView.setText("昵稱:" + user.name);
mAgaView.setText("年齡:" + user.age);
}
@Override
public void onRequestUserResult(int code, User user) {
if(code == 0) {
// 更新LiveData中的數據
mUserLiveData.postValue(user);
} else {
Toast.makeText(this, "刷新失敗", Toast.LENGTH_SHORT).show();
}
}
}
LiveData的observe方法內部進行了雙向注冊,Activity觀察LiveData的數據變化,數據變化時會觸發Activity.onChange方法;LiveData觀察Activity生命周期的變化,當生命周期狀態變更為DESTROYED時(Activity.onDestroy),移除Activity在LiveData中的注冊信息,后續發生數據變化時便不會再通知Activity。
LiveData類已經幫我們做了很多事了,所有必要的注冊邏輯都封裝在里面了,我們只需要調用一個observe方法即可。
LiveData類提供了兩個刷新數據的方法,分別是setValue和postValue,前者必須在主線程中調用,后者沒有線程限制會自動post到主線程中。
多個界面可以共享一個LiveData對象,當數據發生變化時,這些界面都可以觀測到,適應于全局性的數據(比如用戶信息)。
3、ViewModel
之前已經講過,VM的作用類似于C、P,這里不再過多描述。Android中提供了兩個VM相關的基礎類,分別是ViewModel和AndroidViewModel,后者比前者多了一個Application上下文對象。
查看ViewModel的代碼,會發現代碼非常簡單,就一個空方法onCleared,因此如果是手動new一個ViewModel對象那就沒什么意義了。創建ViewModel對象可以使用ViewModelProvider(使用ViewModelProviders創建ViewModelProvider對象),這樣創建出來的ViewModel對象便有了管理者,會在適當的時機調用它的onCleared方法以便開發者清理資源。另外,ViewModelProvider會根據key緩存ViewModel對象。
使用ViewModel重構后的代碼:
UserViewModel:
public class UserViewModel extends AndroidViewModel implements UserBusiness.UserListener {
private UserBusiness mUserBusiness = UserBusiness.get();
private UserLiveData mUserLiveData;
public UserViewModel(@NonNull Application application) {
super(application);
}
public void observe(LifecycleOwner owner, Observer<User> observer) {
// 加載數據庫緩存中的用戶信息
User user = mUserBusiness.getUser();
mUserLiveData = new UserLiveData();
// LiveData注冊對Activity的監聽,同時Activity注冊對LiveData的監聽
mUserLiveData.observe(owner, observer);
// 更新LiveData中的數據
mUserLiveData.postValue(user);
mUserBusiness.addListener(this);
}
@Override
protected void onCleared() {
mUserBusiness.removeListener(this);
super.onCleared();
}
@Override
public void onRequestUserResult(int code, User user) {
if(code == 0) {
// 更新LiveData中的數據
mUserLiveData.postValue(user);
} else {
Toast.makeText(getApplication(), "刷新失敗", Toast.LENGTH_SHORT).show();
}
}
public void refresh() {
mUserBusiness.requestUser();
}
}
Activity又成功地從控制層+視圖層轉變成單純的視圖層了。
四、AAC結合DataBinding
通過上面的幾次重構,代碼已經分層得很好了,下面直接貼代碼:
目錄結構:
XML布局:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="user"
type="com.ecactus.androidappframework.mvvm2.model.User" />
<variable
name="host"
type="com.ecactus.androidappframework.mvvm2.viewModel.UserViewModel"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text='@={user.name}'
android:id="@+id/tv_name"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text='@{"年齡:" + String.valueOf(user.age)}'/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="20dp"
android:text="刷新"
android:onClick="@{host.onRefresh}"/>
</LinearLayout>
</layout>
UserViewModel
public class UserViewModel extends AndroidViewModel implements UserBusiness.UserListener, Observer<User> {
private UserBusiness mUserBusiness = UserBusiness.get();
private UserLiveData mUserLiveData;
private User mUser;
public UserViewModel(@NonNull Application application) {
super(application);
}
public void observe(LifecycleOwner owner, ActivityUserBinding binding) {
// 加載數據庫緩存中的用戶信息
mUser = mUserBusiness.getUser();
if(mUser == null) {
mUser = new User();
}
binding.setUser(mUser);
binding.setHost(this);
mUserLiveData = new UserLiveData();
// LiveData注冊對Activity的監聽,同時Activity注冊對LiveData的監聽
mUserLiveData.observe(owner, this);
// 更新LiveData中的數據
mUserLiveData.postValue(mUser);
mUserBusiness.addListener(this);
}
@Override
protected void onCleared() {
Log.i("UserViewModel", "onCleared");
mUserBusiness.removeListener(this);
super.onCleared();
}
@Override
public void onRequestUserResult(int code, User user) {
if(code == 0) {
// 更新LiveData中的數據
mUserLiveData.postValue(user);
} else {
Toast.makeText(getApplication(), "刷新失敗", Toast.LENGTH_SHORT).show();
}
}
public void onRefresh(View v) {
mUserBusiness.requestUser();
}
@Override
public void onChanged(@Nullable User user) {
mUser.setName(user.name);
mUser.setAge(user.age);
}
}
UserActivity
public class UserActivity extends FragmentActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user);
ActivityUserBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_user);
// 獲取ViewModel
ViewModelProvider.AndroidViewModelFactory instance = ViewModelProvider.AndroidViewModelFactory
.getInstance(getApplication());
UserViewModel userViewModel = new ViewModelProvider(this, instance).get(UserViewModel.class);
userViewModel.observe(this,binding);
}
}
這里只貼出了部分代碼,其他代碼在https://gitee.com/zyd_gitee/androidappframework.git
本文參考了https://www.haomeiwen.com/subject/uymjmqtx.html