本文讲解 LiveData 用法,以及 LiveData 源码解析。

官方文档:https://developer.android.google.cn/topic/libraries/architecture/livedata

一句话介绍 LiveData :LiveData 是一种可观察的数据存储器类。

 

与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。

 

为什么需要 LiveData:

  • 能够保证数据和 UI 统一(跟 LiveData 采用观察者模式有关,LiveData 是被观察的,当数据有变化时它会通知 UI 界面来更新数据。)
  • 减少内存泄漏(在 LiveData 中,能够感知到组件的生命周期,当组件的生命周期处于未激活状态或已经处于 Destroy 状态的时候,观察者就会被清理掉。)
  • 当 Activity 停止时不会引起崩溃(因为 Stop 时就已经变成非激活状态,在 LiveData 分发数据的过程中此时这个组件是非激活状态,LiveData 就不会给它分发数据,其实在组件处于 Pause 时就已经不给他分发数据了,只有它再次 Resume 的时候会重新灌入数据。)
  • 不需要额外的手动处理来响应生命周期的变化(因为它内部有观察生命周期 Lifecycle 的组件)
  • 组件和数据相关的内容能实时更新(当组件从后台来到前台时,LiveData 能够将最新的数据通知组件,灌入到组件里面,保证了组件和数据相关的内容能够实时的更新。)
  • 针对 Configuration Change 时,不需要额外的处理来保存数据(因为在屏幕发生改变时,ViewModel 不会变,当它重建的时候会取得上一次的 ViewModel ,ViewModel 对应的也是之前的 LiveData 。LiveData 中的数据没有变,自然的它在重建过程中 LiveData 数据会时时的再次通知到已经重建的新组件中。)
  • 资源共享(通过继承 LiveData ,将类定义成单例模式,在该类封装一些监听系统属性变化,然后通知 LiveData 的观察者。)

 

注:本文使用 Kotlin 编写。

 

导入 LiveData 库:implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"

 

一、用法

1. 自定义布局,一个 TextView ,两个 Button

<?xml version="1.0" encoding="utf-8"?>        

2. 自定义 ViewModel 类,在 ViewModel 中改变 LiveData 数据的值。

class MainViewModel : ViewModel() {    val TAG = "MainViewModel"    val liveData = MutableLiveData()    var stop = false    fun start() {        liveData.postValue(0)        object : Thread() {            override fun run() {                while (!stop) {                    sleep(1000)                    val value = liveData.value                    liveData.postValue(value?.plus(1))                    Log.d(TAG, "run: " + liveData.value.toString())                }            }        }.start()    }    fun stop() {        stop = true    }}

3. 在 Activity 里观察 LiveData

class MainActivity : AppCompatActivity() {    lateinit var mainViewModel: MainViewModel    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)        mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)        mainViewModel.liveData.observe(this, Observer {            tv_content.text = it.toString()        })        btn_start.setOnClickListener {            mainViewModel.start()        }        btn_stop.setOnClickListener {            mainViewModel.stop()        }    }}

4. 执行程序,点击 Start Button ,每隔1s,数据会发生改变;点击 Stop Button ,线程关闭,数据不再发生改变。

 

二、源码解析

1. MutableLiveData 源码:

public class MutableLiveData extends LiveData {    public MutableLiveData(T value) {        super(value);    }    public MutableLiveData() {        super();    }    @Override    public void postValue(T value) {        super.postValue(value);    }    @Override    public void setValue(T value) {        super.setValue(value);    }}

MutableLiveData 是对 LiveData 的拓展。因为 LiveData 是一个 abstract 的 class ,并不能直接使用。

 

2. LiveData 类图:

观察上面的类图,它有两个实现类,一个是 MutableLiveData ,另一个是 MediatorLiveData 。内部包含了一个 LifecycleBoundObsOvserver ,它实现了 Lifecycle 的 Observer ,它里面的 Observer 进行了对组件生命周期的观察。所以 LiveData 才有了观察组件生命周期的能力。

 

LiveData 函数说明:

  • observe()                       观察函数
  • setValue()                      设置值,必须在主线程调用,直接去改变 UI 界面
  • postValue()                    设置值,主线程或子线程都可以使用,不需要手动切换线程
  • getValue()                      取值
  • hasActiveObservers()  是否有激活状态下的组件
  • hasObservers()             是否有观察者
  • observeForever()          不管 Lifecycle 是不是激活状态,永远都去观察
  • removeObserver()        移除观察者
  • onActive()                      激活回调
  • onInactive()                   解除激活回调,也就是非激活状态

 

实现了 LifecycleEventObserver 接口,用来观察组件生命周期。

 

<> Observer 用来观察 LiveData 内部 value 的一个观察者。

 

大体流程:LiveData post 或 set value 的时候,首先通过 hasObservers 判断是否有观察者,如果没有就不进行分发,如果有就通过 onActive 遍历是否是激活状态,如果是激活状态就会去调用 <> Observer 的回调方式,通知它去更新 UI 界面。

 

3. LiveData.observe() 源码

public void observe(LifecycleOwner owner, Observer < ?super T > observer) {    assertMainThread("observe");    if (owner.getLifecycle().getCurrentState() == DESTROYED) {        // ignore        return;    }    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);    if (existing != null && !existing.isAttachedTo(owner)) {        throw new IllegalArgumentException("Cannot add the same observer" + " with different lifecycles");    }    if (existing != null) {        return;    }    owner.getLifecycle().addObserver(wrapper);}

传进来的 owner 是 Activity 或 Fragment ,然后把 observer 观察者也传进来。

首先判断是否是 DESTROYED 状态,如果是就 return 。

然后会 new 一个 LifecycleBoundObserver ,用来处理生命周期。

把 wrapper put 到 mObservers 容器里面,这个容器是用来遍历用的。

owner 获取 getLifecycle ,添加生命周期观察者 addObserver 。

 

4. LiveData.postValue() 源码

protected void postValue(T value) {    ...    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);}

 因为它可以在子线程进行分发,所以它要 postToMainThread 到主线程去:

private final Runnable mPostValueRunnable = new Runnable() {    @Override    public void run() {        ...        setValue((T) newValue);    }};

它最终调的还是 setValue() 。所以说 setValue() 是在主线程进行调用。

 

5. LiveData.setValue() 源码

protected void setValue(T value) {    assertMainThread("setValue");    mVersion++;    mData = value;    dispatchingValue(null);}

在 set 或 post 时,它的 mVersion 会更新一下,内部的 mData 会被赋值新的 value 。

 

6. LiveData.dispatchingValue() 源码

void dispatchingValue(ObserverWrapper initiator) {    // 判断是否正在进行分发动作,如果正在进行就直接 return 。    if (mDispatchingValue) {        mDispatchInvalidated = true;        return;    }    mDispatchingValue = true;    // 执行 do while 循环    do {        mDispatchInvalidated = false;        if (initiator != null) {            considerNotify(initiator);            initiator = null;        } else {            // 遍历,通过 Map 进行存储            for (Iterator < Map.Entry < Observer < ?super T > , ObserverWrapper >> iterator = mObservers.iteratorWithAdditions(); iterator.hasNext();) {                // 这里的 iterator.next() 对应的是 ObserverWrapper 。                considerNotify(iterator.next().getValue());                if (mDispatchInvalidated) {                    break;                }            }        }    } while ( mDispatchInvalidated );    mDispatchingValue = false;}

 

7. LiveData.considerNotify() 源码

private void considerNotify(ObserverWrapper observer) {        // 判断是否是激活状态,如果是非激活状态直接 return 。    if (!observer.mActive) {        return;    }    // 判断是否是激活状态,如果是非激活状态直接 return 。    if (!observer.shouldBeActive()) {        observer.activeStateChanged(false);        return;    }    // 判断 当前版本 大于等于 LiveData 总的版本号,就不会继续分发。    if (observer.mLastVersion >= mVersion) {        return;    }    // 把当前的 Version 赋值给 observer 。    observer.mLastVersion = mVersion;    observer.mObserver.onChanged((T) mData);}

这个函数解释了 Activity 不会被重复回调的原因。

把 mData 传给当前的 observer 。比如我们的 MainActivity 里面的代码:

mainViewModel.liveData.observe(this, Observer {    ...})
public interface Observer {    void onChanged(T t);}

最终会回调到 Observer {} 里去执行 tv_content.text = it.toString() 。

 

 

如果本文对你有帮助,请点赞支持!!!

 

更多相关文章

  1. 一句话锁定MySQL数据占用元凶
  2. 关于android 数据库SQLite的使用日记
  3. 四大组件及Window简要运行时序图
  4. Android———ContentProvider理解与使用
  5. LibGDX学习-LibGDX基本框架
  6. 我的android 第24天 - ContentUris和ContentProvider
  7. Android(安卓)Service组件
  8. Android系统架构和四大组件
  9. Media-媒介(媒体、介质)【译】

随机推荐

  1. Android集成ShareSDK第三方分享和登录
  2. Android之自定义最简单的竖向引导页
  3. 自定义React Native Modal,支持全屏弹框
  4. 安卓64位计算的转变
  5. ADB Interface驱动安装[Android(安卓)Stu
  6. Android使用Gallery实现照片拖动的特效
  7. 5张图片解决android studio报错:Failed to
  8. Android(安卓)stdio笔记
  9. Android无限循环滚动
  10. 「 五套方案 」解决 Android(安卓)studio