提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一、LiveData是什么?
引导语:ViewModel是用来存放页面的数据,当数据发生变化的时候,需要通知页面进行更新, 可以使用接口完成这个需求(数据多的时候,需要定义的接口就很多),也可以使用LiveData完成,后者可以使其变得更加简单。
LiveData的本质是观察者模式,能感知页面的生命周期,只有页面活动的时候才会进行通知,避免了内存的泄露,一般都是结合View Model使用,通过LiveData包装需要观察的数据,并在其界面进行监听,当数据发生变化的时候,界面就能收到通知,从而更新UI.
二、使用步骤
1.先定义一个类继承ViewModel
代码如下(示例):
注意:LiveData是一个抽象类,不能直接被使用,通常使用的是其子类MutableLiveData
public class ShareDataViewModel extends ViewModel {
private MutableLiveData<Integer> progress;
//通过LiveData的子类MutableLiveData拿到实例对象
public LiveData<Integer> getProgress(){
if (progress==null){
progress=new MutableLiveData<>();
}
return progress;
}
@Override
protected void onCleared() {
super.onCleared();
progress=null;
}
}
2.读入数据
代码如下(示例):
核心代码:(固定步骤)
/*
注意:这里ViewModelProvider(getActivity()中的参数需要的是Activity,而不是Fragment,否则将收不到监听
*/
//1.先通过ViewModelProvider拿到ViewModel
ShareDataViewModel shareDataViewModel=new ViewModelProvider(this.getActivity())
.get(ShareDataViewModel.class);
//2.通过ViewModel拿到实例
final MutableLiveData<Integer> liveData= (MutableLiveData<Integer>) shareDataViewModel.getProgress();
//3.通过observe方法观察ViewModel中字段数据的变化,并在变化时得到通知
liveData.observe(getViewLifecycleOwner(), new Observer<Integer>() {
@Override
public void onChanged(Integer process) {
seekBar.setProgress(process);//更新UI
}
});
public class OneFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View parentView = inflater.inflate(R.layout.fragment_one, container, false);
final SeekBar seekBar = parentView.findViewById(R.id.seekBar);
/*
注意:这里ViewModelProvider(getActivity()中的参数需要的是Activity,而不是Fragment,否则将收不到监听
*/
//1.先通过ViewModelProvider拿到ViewModel
ShareDataViewModel shareDataViewModel=new ViewModelProvider(this.getActivity())
.get(ShareDataViewModel.class);
//2.通过ViewModel拿到实例
final MutableLiveData<Integer> liveData= (MutableLiveData<Integer>) shareDataViewModel.getProgress();
//3.通过observe方法观察ViewModel中字段数据的变化,并在变化时得到通知
liveData.observe(getViewLifecycleOwner(), new Observer<Integer>() {
@Override
public void onChanged(Integer process) {
seekBar.setProgress(process);//更新UI
}
});
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int process, boolean fromUser) {
//当用户操作SeekBar时候,更新ViewModel中的数据
liveData.setValue(process);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
return parentView;
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<fragment
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/fragmentOne"
android:name="com.example.livedatademo.OneFragment"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#00ff88"/>
<fragment
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/fragmentTwo"
android:name="com.example.livedatademo.TwoFragment"/>
</LinearLayout>
fragment_one.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_above="@+id/seekBar"
android:text="Fragment_One"/>
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/seekBar"
android:layout_marginTop="20dp"
android:layout_centerInParent="true"
android:max="100"/>
</RelativeLayout>
核心内容
liveData.observe
监听数据的变化
liveData.postValue()/liveData.setData()更新UI
liveData.postValue()用在非UI线程
liveData.setData()用在UI线程
总结
LiveData的本质是观察者模式
,并且它能感知页面的生命周期,只在页面存活时才会进行通知,从而避免了内存泄漏
。当然你也可以使用observeForever()
方法让 LiveData忽略页面的生命周期,但用完后,一定要记得使用removeObserver()
方法移除监听,否则会造成内存泄漏。
LiveData 大部分时候是在ViewModel中使用的。但它的作用不止于此LiveData在其他地方也能发挥重要作用。Jetpack在设计之初就充分考虑了组件配合使用的需求。例如,我们在下一章将会学习,LiveData 如何搭配 Room 数据库组件进行使用。