本文僅是閱讀Android Architecture Components的個人總結(jié)酵使。
- Android App開發(fā)的痛點(diǎn)
在開發(fā)AndroidApp時,由于系統(tǒng)的UI Controller(Activity焙糟、Fragment)Component能夠被獨(dú)立啟動并且是無順序的口渔,他們的生命周期不受開發(fā)者的控制,因此當(dāng)我們的數(shù)據(jù)依賴這些組件的生命周期時就會發(fā)生許多問題穿撮。
Android官方指出一個重要的開發(fā)原則是:我們不應(yīng)該把不是處理UI和系統(tǒng)事件的代碼寫在UI Controller中缺脉。
Any code that does not handle a UI or operating system interaction should not be in these classes. Keeping them as lean as possible will allow you to avoid many lifecycle related problems. Don't forget that you don't own those classes, they are just glue classes that embody the contract between the OS and your app.
官方指出第二個重要的原則是drive your UI from a model
Architecture Components
就是遵守上面兩個原則的框架,它保證我們app可以很好的響應(yīng)系統(tǒng)組件的生命周期悦穿,不出現(xiàn)混亂的情況攻礼。同時drive your UI from a model
Handling Lifecycles with Lifecycle-Aware Components
這個其實(shí)原理是很簡單的:UI Controller(Activity、Fragment)是一個LifecycleOwner
,它的生命周期時可以被觀察的栗柒。我們可以向它們上面注冊LifecycleObserver
礁扮,觀察生命周期事件。簡單代碼如下:
創(chuàng)建一個LifecycleObserver
:
public class MainPresenter implements LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
void initView() {
Log.e(TAG, "init View");
}
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
void initData() {
Log.e(TAG, "initData");
}
}
向LifecycleOwner
注冊LifecycleObserver
:
public class MainActivity extends AppCompatActivity implements MainView {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
getLifecycle().addObserver(new MainPresenter());
}
note: 在
Support Library 26.1.0
,AppCompatActivity
和Fragment
都已經(jīng)實(shí)現(xiàn)LifecycleOwner
對于上面這個sample傍衡,可以說簡單的把UI Controller的生命周期相關(guān)方法dispatch給其他組件處理深员,使代碼看起來非常清晰。
LiveData
先看一下使用LiveData
編碼的優(yōu)勢:
- 確保UI狀態(tài)和數(shù)據(jù)狀態(tài)是同步的蛙埂。
- 沒有內(nèi)存泄漏
- 不會由于Activity的Stop而引起crash
- 不需要手動處理組件生命周期
- 不會由于系統(tǒng)config改變而保持?jǐn)?shù)據(jù),比如屏幕旋轉(zhuǎn)
LiveData
是一個包裹數(shù)據(jù)并且可以被觀察的對象遮糖,它可以感知App組件的生命周期(Activity Fragment Service
)绣的。這個特性使:LiveData可以在組件活躍的狀態(tài)(在生命周期內(nèi))下更新數(shù)據(jù)
活躍狀態(tài)是指
START
orRESUMED
。即LiveData在數(shù)據(jù)發(fā)生改變時只把這個改變事件通知給活躍的觀察者,對于不活躍的觀察者是不會通知的屡江。
在給LiveData
注冊Observer
時芭概,可以把LifecycleOwner
和LiveData
組成一個配對關(guān)系。這樣在LifecycleOwner
不活躍時惩嘉,Observer
會被移除罢洲。這樣就保證像Activity Fragment
在觀察LiveData
變化時是非常安全的,即在不活躍時文黎,是不會響應(yīng)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;
}
}
MutableLiveData
是一個LiveData
,是一個可被觀察的對象。官方是推薦把LiveData
寫在ViewModel
中的:
- 可以避免Activity和Fragment的臃腫耸峭,這些UI Controller只是響應(yīng)UI的變化桩蓉,而不會持有UI的狀態(tài)
- 解耦LiveData和UIController
對于ViewModel
將會在下面介紹。
通過observer()
方法將LifecycleOwner和LiveData
建立聯(lián)系:
public class NameActivity extends AppCompatActivity {
private NameViewModel mModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get the ViewModel.
mModel = ViewModelProviders.of(this).get(NameViewModel.class);
// Create the observer which updates the UI.
final Observer<String> nameObserver = new Observer<String>() {
@Override
public void onChanged(@Nullable final String newName) {
// Update the UI, in this case, a TextView.
mNameTextView.setText(newName);
}
};
});
// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
mModel.getCurrentName().observe(this, nameObserver);
}
}
上面把一個Observer
加入到LiveData
的觀察者列表劳闹,如果Oberver
對應(yīng)的LifeOwner
(UI Controller)不活躍了院究,這個Observer
將會被移除。
數(shù)據(jù)變化本涕,觸發(fā)活躍的LifeOwner
更新UI,即調(diào)用Observer
的onChanged()
方法业汰。
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String anotherName = "John Doe";
mModel.getCurrentName().setValue(anotherName);
}
});
ViewModel
這個類被設(shè)計用來管理和UI相關(guān)的數(shù)據(jù)(即LiveData
),它允許數(shù)據(jù)感知系統(tǒng)的配置變化,比如屏幕旋轉(zhuǎn)菩颖。
ViewModel在發(fā)生屏幕旋轉(zhuǎn)事件是蔬胯,這個對象會被保留,如果此時UI Controller銷毀了(Activity)位他,在Activity實(shí)例重建的時候氛濒,這個對象是可以被重新獲得的,即我們可以不用在
onSaveInstanceState()
保存數(shù)據(jù)鹅髓,然后在onCreate()
中恢復(fù)舞竿。
可以這樣獲得一個ViewModel
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.
}
@Override
protected void onCleared() {
super.onCleared();
}
}
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
});
}
}
ViewModel的生命周期如下:
即這個對象作用域直到Activity destroy。當(dāng)框架層面Activity被銷毀時窿冯,ViewModel
的onCleared
方法會被調(diào)用骗奖。
官方建議:ViewModel
不應(yīng)該引用任何UI Controller相關(guān)對象。它也不應(yīng)該關(guān)心任何UI Controller的生命周期變化醒串。
如果你需要一個 Application Context
执桌,可以使用 AndroidViewModel
在多個Fragment中的應(yīng)用
在上面可以看出一個ViewModel
其實(shí)適合LifecycleOwner
綁定的,因此Activity下的Fragment可以獲得同一個ViewModel
,即可以交流芜赌。
比如下面的代碼:
Notice that both fragments use getActivity() when getting the ViewModelProvider. As a result, both fragments receive the same SharedViewModel instance, which is scoped to the activity.
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.
});
}
}
總結(jié)
通過上面的介紹仰挣,我們可以通過Lifecycle、LiveData缠沈、ViewModel
這三個對象寫出一個比較穩(wěn)定的app架構(gòu):代碼邏輯清晰,生命周期管理方便等優(yōu)點(diǎn)膘壶。
Demo地址:https://github.com/SusionSuc/ArchitectureComponentSmale