JetPack之LiveData(数据持有类)解析
介绍
简单地说,LiveData是一个数据持有类。它采用了观察者模式。
更具体点来说:LiveData是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
特点
(1)数据可以被观察者订阅;
(2)能够感知组件(Fragment、Activity、Service)的生命周期;
(3)只有在组件出于激活状态(STARTED、RESUMED)才会通知观察者有数据更新;
PS: 文中提到的“组件”皆指实现了LifecycleOwner接口Fragment、Activity。
优点
(1)确保界面符合数据状态
LiveData 遵循观察者模式。当生命周期状态发生变化时,LiveData 会通知 Observer 对象。观察者可以在每次发生更改时更新界面,而不是在每次应用数据发生更改时更新界面。
(2)不会发生内存泄漏
观察者会绑定到 Lifecycler对象,并在其关联的生命周期遭到销毁后进行自我清理。
(3)不会因 Activity 停止而导致崩溃
如果观察者的生命周期处于非活跃状态(如返回栈中的 Activity),则它不会接收任何 LiveData 事件。
(4)不再需要手动处理生命周期
界面组件只是观察相关数据,不会停止或恢复观察。LiveData 将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化。
(5)数据始终保持最新状态
如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的 Activity 会在返回前台后立即接收最新的数据。
(6)适当的配置更改
如果由于配置更改(如设备旋转)而重新创建了 Activity 或 Fragment,它会立即接收最新的可用数据。
(7)共享资源
可以使用单例模式扩展LiveData对象以封装系统服务,以便在应用中共享它们。LiveData对象连接到系统服务一次,然后需要相应资源的任何观察者只需观察LiveData对象。
用法
第一步:创建LiveData
public class DemoData extends LiveData<DemoData> {
private int tag1;
private int tag2;
public int getTag1() {
return tag1;
}
public void setTag1(int tag1) {
this.tag1 = tag1;
postValue(this);
}
public int getTag2() {
return tag2;
}
public void setTag2(int tag2) {
this.tag2 = tag2;
postValue(this);
}
}
【解析】
首先LiveData其实与数据实体类(POJO类)是一样的东西,它负责暂存数据。
其次LiveData其实也是一个观察者模式的数据实体类,它可以跟它注册的观察者回调数据是否已经更新。
最后LiveData还能知晓它绑定的Activity或者Fragment的生命周期,它只会给前台活动的activity回调(这个很厉害)。
第二步:需要在ViewModel实例化DemoData这个类:
public class DemoViewModel extends ViewModel {
private DemoData mDemoData = new DemoData();
public DemoData getDemoData() {
return mDemoData;
}
}
第三步:需要在Activity或者Fragment绑定
public class Demo2Activity extends AppCompatActivity {
private static final String TAG = "Demo2Activity";
private Button mBtnAddData;
private DemoViewModel mDemoViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo2);
mBtnAddData = findViewById(R.id.btn_add_data);
mDemoViewModel = ViewModelProviders.of(this).get(DemoViewModel.class);//获取ViewModel,让ViewModel与此activity绑定
mDemoViewModel.getDemoData().observe(this, new Observer<DemoData>() { //注册观察者,观察数据的变化
@Override
public void onChanged(DemoData demoData) {
Log.e(TAG, "onChanged: 数据有更新");
}
});
mBtnAddData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "onClick: 已经点击");
mDemoViewModel.getDemoData().setTag1(123); //这里手动用按键点击更新数据
}
});
}
}
第四步:结果。点击按键后会有数据更新后的回调触发。
2019-09-18 19:45:53.821 6649-6649/demo.yt.com.demo E/Demo2Activity: onClick: 已经点击
2019-09-18 19:45:53.824 6649-6649/demo.yt.com.demo E/Demo2Activity: onChanged: 数据有更新
总结
第一:创建LiveData实例以存储某种类型的数据。这通常在ViewModel类中完成。
第二:当更新存储在LiveData对象中的值时,它会触发所有已注册的观察者(只要附加的LifecyclerOwner 处于活跃状态)。
第三:LiveData 允许界面控制器观察者订阅更新。当LiveData对象存储的数据发生更改时,界面会自动更新以做出响应。