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。