Viewmodel可以更好地帮助我们将页面与数据从代码上层面上分离开来。使用ViewModel不再需要关心屏幕旋转带来的数据丢失问题。
livedata是一个可被观察的数据容器类,使得数据变成变成被观察者,当数据发生变化时,观察者能够获得通知。
基本使用
添加依赖
def lifecycle_version = "2.5.1"
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
创建ViewModel与LiveData
public class MyViewModel extends ViewModel {
private MutableLiveData<Integer> progress;
public LiveData<Integer> getCurProgress() {
if (progress == null) {
progress = new MutableLiveData<>();
}
return progress;
}
}
在activity使用,当progress改变时,调用onChanged。
MyViewModel myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
MutableLiveData<Integer> data = (MutableLiveData<Integer>) myViewModel.getCurProgress();
data.observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
}
});
}
onChanged会不会在页面销毁后执行?LiveData能够感知页面的声明周期,所以只有页面处于激活状态才会触发
onChanged,在页面销毁时,onChanged不会触发。但使用LiveData.observeForever是个特例,不过页面处于哪种状态,都会调用onChanged方法,所以使用observeForever,得调用removeObserver()来移除观察。
利用ViewModel和LiveData实现fragment间通信
同一个activity中的fragment共享数据。在布局文件中放置两个fragment,这两个fragment的功能是一样的,都是放置了seekbar。控制其中一个另一个也变化,需要注意的是,ViewModelProvider中的第一个参数要 传requireActivity()。
两个fragment功能是一样的,
SeekBar seekBar = view.findViewById(R.id.a_sb);
MyViewModel myViewModel = new ViewModelProvider(requireActivity()).get(MyViewModel.class);
MutableLiveData<Integer> progressLiveData = (MutableLiveData<Integer>) myViewModel.getCurProgress();
progressLiveData.observe(getViewLifecycleOwner(), new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
seekBar.setProgress(integer);
}
});
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
progressLiveData.setValue(progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
效果