LiveData的優點
- 不用手動控制生命周期,當數據變化它只會給前臺活動的activity回調。
- 不用擔心內存泄露。
- 如果一個觀察者處于 Paused 或 Destroyed。 狀態,它將不會受到通知,一旦觀察者重新恢復 Resumed 狀態,它將會收到 LiveData 的最新數據。
ViewModel的優點
為Activity、Fragment存儲數據,直到完全銷毀,不會發生試圖去刷新那些不存在的了View而出現空指針異常。
引入
def lifecycle_version = "1.1.1"
// ViewModel and LiveData
implementation "android.arch.lifecycle:extensions:$lifecycle_version"
// alternatively - just ViewModel
implementation "android.arch.lifecycle:viewmodel:$lifecycle_version"
// alternatively - just LiveData
implementation "android.arch.lifecycle:livedata:$lifecycle_version"
創建MutableLiveData
MutableLiveData是LiveData的子類,添加了公共方法setValue和postValue
public class UserViewModel extends ViewModel {
public MutableLiveData<String> user = new MutableLiveData<>();
}
在Activity或者Fragment綁定
public class DemoActivity extends Activity {
private UserViewModel userViewModel;
private Button mBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
...
userViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
userViewModel.user.observe(this, new Observer<String>() { //注冊觀察者
@Override
public void onChanged(String s) {
Log.e(TAG, "onChanged: 監聽值有變化="+s);
}
});
mBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 改變值
userViewModel.user.setValue("測試");
}
}
}
}
API
1. postValue()
在子線程刷新數據。
2. setValue()
只能在主線程里調用。
3. getValue()
返回當前值。
4. observe
綁定觀察者, 會給此activity或者Fragment在前臺時回調數據(onStarted或者onResumed狀態)。
5. removeObserver(@NonNull final Observer<? super T> observer)
移除指定觀察者。
6. removeObservers(@NonNull final LifecycleOwner owner)
移除當前Activity或者Fragment的全部觀察者。
mMainViewModel.getContent().removeObservers(this);
7. hasActiveObservers()
如果此LiveData具有活動(Activity或者Fragment在前臺,當前屏幕顯示)的觀察者,則返回true。其實如果這個數據的觀察者在最前臺就返回true,否則false。
8. hasObservers()
如果此LiveData具有觀察者,則返回true。
9. observeForever(@NonNull Observer<? super T> observer)
設置永遠觀察者,永遠不會被自動刪除。您需要手動調用removeObserver(Observer)以停止觀察此LiveData,設置后此LiveData,一直處于活動狀態,不管是否在前臺哪里都會獲得回調。
10. onActive()
在LiveData中,onActive方法回調表明當前Activity處于激活狀態,也就是Activity處于生命周期的活動狀態中(onStart,onResume),可以簡單認為當前的Activity處于前臺。
11. onInactive()
LiveData的onInactive處理涉及onActive剩下的生命周期,可以簡單理解onInactive是Android的Activity/Fragment處于未激活(后臺,比如當前Activity處于生命周期的onStop,onPause)。
12. ViewModelProvider.of(@NonNull Fragment fragment, @Nullable Factory factory)
向ViewModel傳參。
public class TestViewModel extends ViewModel {
private final String mKey;
private MutableLiveData<String> mNameEvent = new MutableLiveData<>();
public MutableLiveData<String> getNameEvent() {
return mNameEvent;
}
public TestViewModel(String key) {
mKey = key;
}
public static class Factory implements ViewModelProvider.Factory {
private String mKey;
public Factory(String key) {
mKey = key;
}
@Override
public <T extends ViewModel> T create(Class<T> modelClass) {
return (T) new TestViewModel(mKey);
}
}
public String getKey() {
return mKey;
}
}
ViewModelProviders.of(this, new TestViewModel.Factory(mkey)).get(TestViewModel.class)
使用場景
- 當 config 導致 activity 重新創建的時候,不需要手動取處理數據的儲存和恢復。它已經幫我們封裝好了。
- 多個fragment同步數據。
- 監聽網絡變化處理數據。
- 在Activity處于不可見比如用戶按Home鍵不可見時候,此時可能不希望再做處理,那么就可以在LiveData的onInactive做一個邏輯處理,改變任務的狀態,如果當前Activity又被用戶調回前臺,那么可以在LiveData的onActive重新恢復任務的運行。
建議
- ViewModel(和presenter)不要和Android Framework里的任何類發生關系。
- ViewModel 不應持有 View、Lifecycle、或其他可能持有 Activity 的 Context 的類的引用。
- 其他類不應持有 ViewModel 的引用。在 Activity 或 Fragment 銷毀后,其它任何比 Activity 或 Fragment 生命周期長的類都不應再持有 ViewModel 的引用,否則會影響 ViewModel 被 GC 回收,從而泄露 ViewModel。
- 用一個包裝類或者另一個LiveData來發出數據的狀態,比如可以在ViewModel放出一個LiveData<MyDataState>. 例如, MyDataState 包含數據正在加載中,已經成功加載或加載失敗了3種信息。
- 要有效存取和恢復UI狀態,組合使用persistence, onSaveInstanceState()和 ViewModels。