【1】关于LiveData
① LiveData
,原意是 活着的数据。 数据还能有生命? 先来看下官方的定义:
LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如
Activity/Fragment)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
拆解开来:
- LiveData是一个数据持有者,给源数据包装一层。
- 源数据使用LiveData包装后,可以被observer观察,数据有更新时observer可感知。
- 但 observer的感知,只发生在(
Activity/Fragment
)活跃生命周期状态(STARTED、RESUMED
)。
- 也就是说,LiveData使得 数据的更新 能以观察者模式 被
observer
感知,且此感知只发生在LifecycleOwner
的活跃生命周期状态。
② 使用LiveData的好处:
- 确保界面符合数据状态,当生命周期状态变化时,LiveData通知Observer,可以在observer中更新界面。观察者可以在生命周期状态更改时刷新界面,而不是在每次数据变化时刷新界面。
- 不会发生内存泄漏,observer会在LifecycleOwner状态变为DESTROYED后自动remove。
- 不会因 Activity停止而导致崩溃,如果LifecycleOwner生命周期处于非活跃状态,则它不会接收任何 LiveData事件。
- 不需要手动解除观察,开发者不需要在onPause或onDestroy方法中解除对LiveData的观察,因为LiveData能感知生命周期状态变化,所以会自动管理所有这些操作。
- 数据始终保持最新状态,数据更新时 若LifecycleOwner为非活跃状态,那么会在变为活跃时接收最新数据。例如,曾经在后台的Activity 会在返回前台后,observer立即接收最新的数据。
【2】使用LiveData
- 导入依赖
- 创建LiveData实例,指定源数据类型
- 创建Observer实例,实现onChanged()方法,用于接收源数据变化并刷新UI
- LiveData实例使用observe()方法添加观察者,并传入LifecycleOwner
- LiveData实例使用setValue()/postValue()更新源数据 (子线程要postValue())
public class LiveDataTestActivity extends AppCompatActivity{
private MutableLiveData<String> mLiveData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lifecycle_test);
//liveData基本使用
mLiveData = new MutableLiveData<>();
mLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.i(TAG, "onChanged: "+s);
}
});
Log.i(TAG, "onCreate: ");
mLiveData.setValue("onCreate");//activity是非活跃状态,不会回调onChanged。变为活跃时,value被onStart中的value覆盖
}
@Override
protected void onStart() {
super.onStart();
Log.i(TAG, "onStart: ");
mLiveData.setValue("onStart");//活跃状态,会回调onChanged。并且value会覆盖onCreate、onStop中设置的value
}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG, "onResume: ");
mLiveData.setValue("onResume");//活跃状态,回调onChanged
}
@Override
protected void onPause() {
super.onPause();
Log.i(TAG, "onPause: ");
mLiveData.setValue("onPause");//活跃状态,回调onChanged
}
@Override
protected void onStop() {
super.onStop();
Log.i(TAG, "onStop: ");
mLiveData.setValue("onStop");//非活跃状态,不会回调onChanged。后面变为活跃时,value被onStart中的value覆盖
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy: ");
mLiveData.setValue("onDestroy");//非活跃状态,且此时Observer已被移除,不会回调onChanged
}
}
注意到 LiveData实例mLiveData的创建是使用MutableLiveData,它是LiveData的实现类,且指定了源数据的类型为String。然后创建了接口Observer的实例,实现其onChanged()方法,用于接收源数据的变化。observer和Activity一起作为参数调用mLiveData的observe()方法,表示observer开始观察mLiveData。然后Activity的所有生命周期方法中都调用了mLiveData的setValue()方法。 结果日志打印如下:
//打开页面,
2020-11-22 20:23:29.865 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onCreate:
2020-11-22 20:23:29.867 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onStart:
2020-11-22 20:23:29.868 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onChanged: onStart
2020-11-22 20:23:29.869 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onResume:
2020-11-22 20:23:29.869 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onChanged: onResume
//按Home键
2020-11-22 20:23:34.349 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onPause:
2020-11-22 20:23:34.349 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onChanged: onPause
2020-11-22 20:23:34.368 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onStop:
//再点开
2020-11-22 20:23:39.145 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onStart:
2020-11-22 20:23:39.146 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onChanged: onStart
2020-11-22 20:23:39.147 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onResume:
2020-11-22 20:23:39.147 13360-13360/com.hfy.androidlearning I/Lifecycle_Test: onChanged: onResume
//返回键退出
2020-11-22 20:23:56.753 14432-14432/com.hfy.androidlearning I/Lifecycle_Test: onPause:
2020-11-22 21:23:56.753 14432-14432/com.hfy.androidlearning I/Lifecycle_Test: onChanged: onPause
2020-11-22 20:23:58.320 14432-14432/com.hfy.androidlearning I/Lifecycle_Test: onStop:
2020-11-22 20:23:58.322 14432-14432/com.hfy.androidlearning I/Lifecycle_Test: onDestroy:
-
使用讲解
-
首先打开页面,
onCreate()
中setValue
,由于activity是非活跃状态,不会立即回调onChanged
。当走到onStart()变为活跃时,onChanged
被调用,但value被onStart()
中setValue的value覆盖,所以打印的是onChanged: onStart
。(为啥不是连续打印两次呢?,是因为ON_START
事件是在onStart() return
之后,即onStart()走完之后才变为活跃,此时observer接收最新的数据。) 接着走到onResume(),也setValue了,同样是活跃状态,所以立刻回调onChanged
,打印onChanged: onResume
-
按Home键时,
onPause()
中setValue,活跃状态,立刻回调onChanged
方法。onStop()执行时已经变为非活跃状态,此时setValue
不会立即回调onChanged
方法。 -
再点开时,走到
onStart()
变为活跃时,onChanged
被调用,但value被onStart()
中setValue的value覆盖,所以打印的是onChanged: onStart。接着走到onResume()
,也setValue
了,同样是活跃状态,所以立刻回调onChanged
。 -
返回键退出时,
onPause()/onStop()
的效果和按Home键一样。onDestroy()中setValue
,此时非活跃状态,且此时observer
已被移除,不会回调onChanged
。
另外,除了使用observe()方法添加观察者,也可以使用observeForever(Observer) 方法来注册未关联 LifecycleOwner的观察者。在这种情况下,观察者会被视为始终处于活跃状态。