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仍然可以持有状态。

11-19 01:46