LiveData原理分析
1 LiveData简介
大部分Android应用会从网络或SQLite数据库存取数据,并根据数据更新界面。为了避免ANR,主线程中不能存取数据。而后台线程中无法更新界面。通常的做法是让后台线程将数据通过Handler传递给主线程。但是当界面较为复杂时,使用Handler这种方式变得非常复杂。为了简化界面更新的工作,Google在Jetpack中提供了LiveData组件。LiveData具有保证UI和状态一致、避免内存泄漏、避免手动管理生命周期等优点。
2 LiveData用法
LiveData是一个在线程间传递数据的容器。当后台线程得到数据后,通过postValue()方法投递数据。其他线程通过getValue()得到数据。为了通知其他线程,LiveData采用的观察者模式。通过observe()方法,主线程可以在数据更新后立即得到通知。下面是一个简单的例子:
public class BackgroundThread extends Thread {
public BackgroundThread(LiveData<Data> aLiveData) {
liveData = aLiveData;
}
@Override
public void run() {
Data data = readDataFromFile();
liveData.postValue(data);
}
}
public MainActivity extends AppCompatActivity {
private LiveData<Data> liveData = new MutableLiveData<>();
private BackgroundThread thread = new BackgroundThread(liveData);
private TextView textview;
@Override protected onCreate(Bundle bundle) {
// ...
liveData.observe(this, new Observer<Data>() {
@Override
public void onChanged(Data data) {
textview.setText(data.getText());
}});
}
}
从例子里可以看到,observe()方法有两个参数,第二个参数是观察者。那么第一个参数是什么呢?第一个参数的类型是LifecycleOwner,加入LifecycleOwner的目的是自动管理Activity生命周期。这一点在后面会进行介绍。
LiveData类定义在android.arch.lifecycle中,使用时需要在build.gradle引入依赖项:
implementation "android.arch.lifecycle:extensions:1.1.1"
3 数据的传递
实际上LiveData传递数据的方法也是通过Handler。在postValue()方法中,LiveData调用ArchTaskExecutor.postToMainThread(),将一个Runnable对象传递给主线程。这个Runnable对象调用setValue()对数据进行更新。
更新数据的时候,LiveData首先将版本号加1,然后遍历观察者。如果观察者处于活跃状态(Lifecycle.State是STARTED或RESUMED),并且观察者的版本号小于LiveData,LiveData会调用观察者的onChanged()方法进行通知。
4 生命周期管理
这一段简单介绍一下生命周期管理。当观察者的生命周期不是STARTED或RESUMED时,数据更新不会进行通知。这是怎么实现的呢?在调用observe()时,第一个参数是LifecycleOwner,第二个参数是Observer。LiveData建立一个LifecyleBoundObserver对象,将这两个参数绑定到一起,来接收Lifecycle的生命周期更新和LiveData的数据更新。LifecycleBoundObserver是一个的内部类,它持有了LiveData引用。当生命周期发生变化(LifecycleRegistry.handleLifecyleEvent)时,LifecycleBoundObserver调用LiveData的dispatchingValue()方法,获取最新数据。
5 Lifecycle
Lifecycle生命了Android生命周期。Lifecycle包括6个状态和7个事件,分别是:
| 状态 || DESTROY || INITIALIZED || CREATED || STARTED || RESUMED |
| 事件 || ON_CREATE || ON_START || ON_RESUME || ON_PAUSE || ON_STOP || ON_DESTROY || ON_ANY |
6 Room
Room是Jetpack提供的SQLite ORM工具。Room中存取数据的方法都是阻塞的,要在后台执行,因此非常适合与LiveData配合使用。Room中定义的Dao可以返回LiveData,当SQLite查询返回后,对界面进行更新。
7 ViewModel
另一个经常和LiveData搭配使用的是ViewModel。ViewModel用于管理Activity或Fragment中的各LiveData对象。可以把ViewModel看成是LiveData的集合。ViewModel的优点是可以和Activity或Fragment绑定在一起,并且在配置改变引起的Activity/Fragment销毁时,ViewModel仍然可以持有状态。