Android LiveData的使用和原理分析

简介和使用

官方对LiveData的定义是:一种可观察的数据存储器类;具有以下优点:

  • 采用观察者模式,无需在数据发生变化时更新界面便能确保界面符合数据状态;
  • 具有生命周期感知能力,不需要手动处理生命周期,不仅遵循其他组件的生命周期。而且可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
  • 观察者绑定到了Lifecycle对象,会自动进行清理,不会发生内存泄露; 同一个观察者只能和一个Lifecycle绑定;
  • 数据始终维持最新的状态,生命周期变为非活跃状态,它会在再次变为活跃状态时展示最新的数据(当Activity生命周期发生变化,重新回到活跃状态时会显示最新的数据)

基本使用方法:

创建:

kotlin 复制代码
class LiveDataViewModel : ViewModel() {
    val currentCount: MutableLiveData<Int> by lazy {
        MutableLiveData(0)
    }
}

使用:

kotlin 复制代码
class LiveDataActivity : AppCompatActivity() {
    val viewModel: LiveDataViewModel by viewModels()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_live_data)
        val textView = findViewById<TextView>(R.id.tv1)
        //添加监听,观察 LiveData 对象
        viewModel.currentCount.observe(this, Observer<Int> {
            textView.text = "$it"
        })
        findViewById<Button>(R.id.button).setOnClickListener {
                //更新 LiveData 对象数据
            viewModel.currentCount.value = viewModel.currentCount.value?.plus(1)
        }
    }
}

核心结构

LiveData本身是一个持有数据的被观察者容器,首先看下它的核心代码结构:

java 复制代码
public abstract class LiveData<T> {
    private volatile Object mData;
    static final int START_VERSION = -1;
    private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
            new SafeIterableMap<>();
    private int mVersion;
    private final Runnable mPostValueRunnable = new Runnable() {
        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
            }
            setValue((T) newValue);
        }
    };
    public LiveData(T value) {
        mData = value;
        mVersion = START_VERSION + 1;
    }
    public LiveData() {
        mData = NOT_SET;
        mVersion = START_VERSION;
    }
    private void considerNotify(ObserverWrapper observer) {
        //通知观察者之前需要确定观察者处于活跃状态
        if (!observer.mActive) {
            return;
        }
        //通知观察者之前需要确定观察者的数据版本
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //通知观察者数据更新
        observer.mObserver.onChanged((T) mData);
    }
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        // 循环遍历观察者
        for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
             mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
            considerNotify(iterator.next().getValue());
        }
    }
    //观察者注册
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        // 关键代码①
        // 注册对Lifecycle的观察,用以监听观察者所在组件的生命周期
        owner.getLifecycle().addObserver(wrapper);
    }
    protected void setValue(T value) {
        //同步更新数据
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }
    protected void postValue(T value) {
        //异步更新数据
        synchronized (mDataLock) {
            mPendingData = value;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }
    public T getValue() {
        Object data = mData;
        if (data != NOT_SET) {
            return (T) data;
        }
        return null;
    }
    public void removeObserver(@NonNull final Observer<? super T> observer) {
        //移除观察者监听
        ObserverWrapper removed = mObservers.remove(observer);
        removed.detachObserver();
        removed.activeStateChanged(false);
    }
    class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {

        final LifecycleOwner mOwner;
        // 判断当前观察者是否处于活跃状态
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }
        // 关键代码②
        //监听观察者所在组件的生命周期变化
        public void onStateChanged(@NonNull LifecycleOwner source,
                                   @NonNull Lifecycle.Event event) {
            Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
            if (currentState == DESTROYED) {
                // 监听生命周期组件是否被销毁
                removeObserver(mObserver);
                return;
            }
            Lifecycle.State prevState = null;
            while (prevState != currentState) {
                // 循环直至生命周期状态同步
                prevState = currentState;
                activeStateChanged(shouldBeActive());
                currentState = mOwner.getLifecycle().getCurrentState();
            }
        }
        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }
    private abstract class ObserverWrapper {
        final Observer<? super T> mObserver;
        int mLastVersion = START_VERSION;
                                boolean mActive;
        ObserverWrapper(Observer<? super T> observer) {
            mObserver = observer;
        }
        void activeStateChanged(boolean newActive) {
            // 观察者活跃状态未变化时直接返回
            if (newActive == mActive) {
                return;
            }
            // 更新观察者活跃状态
            mActive = newActive;
            // 如果是从非活跃状态转换为活跃状态,则立即触发一次数据更新流程
            // 从而确保观察者能拿到最新的数据
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }
}
fun interface Observer<T> {
    fun onChanged(value: T)
}

LiveData 是一个抽象类,它的核心成员变量/常量有四个:

  • mData 用以存储可变化的数据
  • mObservers 存储所有观察者
  • mVersion 标记当前数据mData的版本号
  • START_VERSION 数据的初始版本号

结合上文中的几个核心成员函数,大致可知LiveData 的运转流程如下:

  • LiveData 通过一个Object持有数据,借助mVersion 实现对数据版本的标记
  • LiveData 通过一个Map持有并管理所有观察值,但是并不直接持有观察者Observer ,而是借助ObserverWrapper 子类LifecycleBoundObserver。其中,ObserverWrapper 持有真正的观察者,并标记了观察者所持有数据的版本号,而LifecycleBoundObserver 则通LifecycleEventObserver 接口实现了观察者的生命周期的绑定和监听,同时实现了观察值接触绑定的逻辑。
  • LiveData 提供了两个更新数据的方式setValuepostValue ,前者用于同步更新,后者用以异步更新
  • 每当数据变化时,LiveData 并不会直接通知所有观察者。而是首先会判断观察者的活跃状态 以及其数据版本,然后循环遍历所有观察值,通过Observer.onChanged 通知观察者数据发生了变化

重要提示:以Activity为例,在其生命周期处于onStartonStop 之间时,Lifecycle 会认为它处于活跃状态

对生命周期组件的感知

LiveData 是通过 Lifecycle 实现对生命周期组件的生命周期感知的,其本质上也是一个观察者模式。

需要特别注意关键代码①和②,①处通过注册Lifecycle的监听实现了对生命周期组件的生命周期监听(如Activity)。②是生命周期组件Lifecycle 的观察者,用以响应生命周期组件的生命周期变化。Lifecycle在生命周期发生变化时是会通过onStateChanged 通知观察值数据发生变化。

这两处代码是LiveData 感知生命周期的关键,具体流转过程属于Lifecycle 范畴。这里我们只需要记住以下几点:

  1. LiveData 通过注册Lifecycle的监听实现了对生命周期组件的生命周期监听;
  2. Lifecycle 通过onStateChanged 通知LiveData 组件的生命周期发生变化。
  3. onStateChanged 会根据Lifecycle.Even 判断生命周期组件的生命周期状态,并根据状态做不同的处理,如解除LiveData 观察者、通知LiveData 观察者数据更新。
  4. LiveData 并不直接持有观察者Observer,而是借助一个包装类ObserverWrapper 。目的是实现和生命周期组件的生命周期的绑定

关键代码②还有特别重要的Lifecycle 相关补充:Lifecycle 在注册观察者时,会为观察者管理一个状态,为观察者标记一个 Lifecycle.State ,并为其设置默认值。如果该状态和 Lifecycle 真正的状态不对应,则会立刻触发相关流程进行状态同步,并间接触观察者的 onStateChanged 方法

紧接着,onStateChanged 会根据当前生命周期状态去执行相关操作,通知数据更新或者移除监听等。这也是LiveData 做到 "数据始终维持最新的状态,生命周期变为非活跃状态,它会在再次变为活跃状态时展示最新的数据"的原因。

初始化和添加观察者

初始化

由于LiveData 是一个抽象类,无法直接创建实例,必须借助其子类才可以使用。其中最简单的是使用官方提供的MutableLiveData

java 复制代码
public class MutableLiveData<T> extends LiveData<T> {
    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);
    }
}

它公开了LiveData 更新数据受保护的两个成员函数,在确保LiveData 可被实例化的同时,向外界暴露了更新数据的能力。

ViewModelActivity为例:

kotlin 复制代码
class MainViewModel() : ViewModel() {
    private val _mutableLiveData = MutableLiveData<String>()
    val mutableLiveData: LiveData<String>
        get() = _mutableLiveData

    fun getNewData() {
        _mutableLiveData.value = "New Data"
    }    
}
class MainActivity : ComponentActivity() {
    private val mainViewModel: MainViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mainViewModel.mutableLiveData.observe(this) {
            print(it)
        }
    }    
}

使用非常简单,只需要创建MutableLiveData 对象,在数据消费端通过observe 注册监听。数据生产端通过setValue/postValue即可实现数据的更新。

而这其中,通过对MutableLiveData 成员变量的私有化,和get函数。确保View层拿到的实例的类型为LiveData ,只能注册监听而无法通过访问setValue/postValue 更改数据。依次保证数据源来源的统一性,更好的做到视图和数据层的隔离和职责单一。

添加观察者

LiveData 提供了两种添加观察者的方式:observeobserveForever

  • 前者只会在观察者所有者的生命周期处于活跃状态时才会接受事件,并且在DESTROYED状态将自动移除。
  • 而后者的观察者将接收所有事件,并且不会自动删除,必须手动调用removeObserver 以停止观察此 LiveData。

Activity中使用如下代码可验证:

kotlin 复制代码
class SecondActivity : ComponentActivity() {
    private val mainViewModel: MainViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        mainViewModel.mutableLiveData.observe(this) {
            println("onStop-observe:$it")
        }
        mainViewModel.mutableLiveData.observeForever {
            println("onStop-observeForever:$it")
        }
    }

    override fun onStop() {
        super.onStop()
        println("onStop")
        mainViewModel.mutableLiveData.value = "onStop"
    }

    override fun onDestroy() {
        println("onDestroy")
        //todo
        //销毁之前一定要记得移除observeForever监听
    }

}
/** 输出结果如下:
 * onStop
 * onStop-observeForever:onStop
 * onDestroy
 */

Activity 处于onStop状态时,Lifecycle 会处于非活跃状态。此时通过LiveData 更新数据,只有通过observeForever 注册的观察者才会收到事件通知。

observeobserveForever 的源码如下:

java 复制代码
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    assertMainThread("observe");
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        return;
    }
    LiveData.LifecycleBoundObserver wrapper = new LiveData.LifecycleBoundObserver(owner, observer);
    LiveData.ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    // 如果观察者已经存在,则比较观察者已经关联的LifecycleOwner是否和将要关联的一致
    // 如果不一致,则抛出异常,确保一个观察者只和一个生命周期组件所关联
    if (existing != null && !existing.isAttachedTo(owner)) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    if (existing != null) {
        return;
    }
    // 注册对Lifecycle的观察,用以监听观察者所在组件的生命周期
    owner.getLifecycle().addObserver(wrapper);
}
@MainThread
public void observeForever(@NonNull Observer<? super T> observer) {
    assertMainThread("observeForever");
    LiveData.AlwaysActiveObserver wrapper = new LiveData.AlwaysActiveObserver(observer);
    LiveData.ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    // 如果观察者已经存在,则判断观察者是否为LifecycleBoundObserver子类
    // 如果是,则抛出异常,确保一个观察者只和一个生命周期组件所关联
    if (existing instanceof LiveData.LifecycleBoundObserver) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    if (existing != null) {
        return;
    }
    // 直接使用true表明处于活跃状态
    wrapper.activeStateChanged(true);
}
private class AlwaysActiveObserver extends ObserverWrapper {
    AlwaysActiveObserver(Observer<? super T> observer) {
        super(observer);
    }
    @Override
    boolean shouldBeActive() {
        // 直接返回true,标记永远处于活跃状态
        return true;
    }
}
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
    @NonNull
    final LifecycleOwner mOwner;
    LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
        super(observer);
        mOwner = owner;
    }
    @Override
    boolean shouldBeActive() {
        // 判断当前所关联的组件是否处于活跃状态
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }
    @Override
    public void onStateChanged(@NonNull LifecycleOwner source,
                               @NonNull Lifecycle.Event event) {
        // 响应和处理生命周期组件的生命周期变化
        Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
        if (currentState == DESTROYED) {
            // DESTROYED状态下移除观察者
            removeObserver(mObserver);
            return;
        }
        Lifecycle.State prevState = null;
        while (prevState != currentState) {
            prevState = currentState;
            // 使用shouldBeActive当前组件真正的状态
            activeStateChanged(shouldBeActive());
            currentState = mOwner.getLifecycle().getCurrentState();
        }
    }
    @Override
    boolean isAttachedTo(LifecycleOwner owner) {
        // 比对将要绑定的LifecycleOwner和当前绑定的是否为同一个
        return mOwner == owner;
    }
    @Override
    void detachObserver() {
        // 解除对Lifecycle的观察
        mOwner.getLifecycle().removeObserver(this);
    }
}

二者有两个共同点:

  • 都只能在主线程里调用
  • 都通过ObserverWrapper 实现对真正观察的包装和管理

而不同点在于:

  • observe需要接受一个LifecycleOwner 对象用于实现对生命周期组件的观察,而observeForever 只需要接受观察者
  • observe 在注册前会先判断生命周期组件的生命周期,如果处于*DESTROYED 状态则不会执行注册流程*
  • 它们"确保同一个观察者只能和一个Lifecycle绑定"的方式不同(具体分析在上文源码的注释之中)
  • observe 会通过对Lifecycle 注册监听实现对生命周期组件的生命周期监听和响应具体分析在上文源码的注释之中)而observeForever 则不会
  • observeForever 会立刻通过activeStateChanged 触发dispatchingValue ,执行数据分发流程。而observe 则是在LifecycleBoundObserveronStateChanged 中根据生命组件的状态判断是否触发activeStateChanged 或者解除监听(具体流程参看上文中关键代码②),。

activeStateChanged 的触发机制不同,导致observeobserveForever 的在注册时表现有很大不同。 首先思考一个问题,LiveData 在添加注册时会立刻触发回调吗?

首先,上文说到过:LiveData 在通知观察者之前会比对观察者的数据版本和当前 LiveData 的数据版本。所以,当观察者注册时,如果观察者的数据版本和 LiveData 数据版本一致,则不会触发回调。这种一般有两种情况:

  • LiveData 数据为空且没有修改过,观察者和LiveData 的数据版本号都初始值-1
  • 当前观察者并不是第一次注册,且在上次注册到当前注册之间,LiveData 的数据没有发生过更新

其次,通过observe 的注册的观察者,只有在处于活跃状态时才会被更新。而通过observeForever 添加的观察者在每次数据更新后都能立刻拿到最新数据。原因就它们使用的观察者包装类不同。虽然在注册时它们都会通过ObserverWrapper.activeStateChanged 去触发事件分发函数dispatchingValue 。但是 前者使用LifecycleBoundObserver 监听了Lifecycle 生命周期状态,只在活跃状态时才触发。而后者则将状态永远标记为活跃状态。

数据更新

有三种情况会触发LiveData 的数据更新流程(但并不一定能真正的通知到观察者)。注册观察者时观察者所在生命周期组件发生了变化后 以及通过**setValue/postValue 更改数据后**。前两者本质都是上文中说的生命周期发生改变通过activeStateChanged 触发,在经过判断确认后与**setValue/postValue 一样,**最终都会通过dispatchingValue 遍历通知所有观察者。

dispatchingValue 并没有那么简单,实际流程要比上文中展示的核心代码结构要复杂一些:

ini 复制代码
void dispatchingValue(@Nullable LiveData.ObserverWrapper initiator) {
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {
            considerNotify(initiator);
            initiator = null;
        } else {
            for (Iterator<Map.Entry<Observer<? super T>, LiveData.ObserverWrapper>> iterator =
                 mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

dispatchingValue 核心是遍历所有观察者,通过considerNotify 调用onChanged通知所有观察者数据更新。但并不是简单的对所有观察者进行遍历调用。它通过一个可空的参数initiator,接受一个观察者,用以判断是单独更新还是全量更新。如果initiator 不为空,则仅仅更新initiator 这一个观察者,这种情况只发生在ObserverWrapper.activeStateChanged 中,也就是注册观察者时和生命周期组件的状态发生了改变后。否则就通过遍历更新所有观察者,这种情况有数据改变触发。

它还通过两个变量来控制标记状态:

  • mDispatchInvalidated:标记当前正在分发的数据是否已经失效
  • mDispatchingValue: 标记当前是否正处于数据分发中

dispatchingValue 在开启分发前,首先通过mDispatchingValue 检查当前是否已经处于数据分发过程中。如果正处于分发流程中,则通过mDispatchInvalidated标记当前数据已经失效然后结束当前执行流程。这两个状态配合do-while循环一起确保了当在数据分发过程时修改 LiveData 数据,能立刻判断到当前循环分发中的数据已经失效,并结束掉当前循环,减少不必要的通知。之后再开启的新的循环分发新的数据 。以下面代码为例,为LiveData注册四个观察者,并在第二个观察者中再次更新值:

kotlin 复制代码
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    println("onCreate")
    mainViewModel.liveData.observe(this) {
        println("observe1:$it")
    }
    mainViewModel.liveData.observe(this) {
        println("observe2:$it")
        if (it % 2 != 0) {
            mainViewModel.liveData.value = 2
        }
    }
    mainViewModel.liveData.observe(this) {
        println("observe3:$it")
    }
    mainViewModel.liveData.observe(this) {
        println("observe4:$it")
    }
    button.onClick {
              mainViewModel.liveData.value = 1
    }
}
/**
当按下按钮修改数据后,输出结果如下:
observe1:1
observe2:1
observe1:2
observe2:2
observe3:2
observe3:2
*/

通过输出日志可以发现,第一次将LiveData 的数据修改为1之后,LiveData 按顺序通知所有观察者。当观察者2接收到通知后,再次修改数据为2。此时由于dispatchingValue 正处于事件分发之中。mDispatchingValue 为true,于是会将mDispatchInvalidated 标记为true,表明当前数据已经过期并结束当前调用栈,继续执行当前循环。而当前循环通过mDispatchInvalidated 判断当前数据已经过期,会立刻结束本轮循环。此时do-while发挥功能,开启新的循环。从头遍历通知所有观察者。因此,观察者3和4不会收到数据为1的通知,而是会直接接收到最新的值2。以此防止过期数据导致的不必要的性能开销。

最终的分发是在considerNotify 中通过调用Observer.onChanged 实现的:

ini 复制代码
private void considerNotify(ObserverWrapper observer) {
    if (!observer.mActive) {
        return;
    }
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    observer.mObserver.onChanged((T) mData);
}

在真正调用onChanged之前,首先会判断观察者是否处于活跃状态,以及比对数据版本和观察者的数据版本是否一致。只有在观察者处于活跃状态且观察者的数据版本滞后,才会通知观察者。

不仅如此,在调用之前还会二次检验Observer.shouldBeActive 检查状态。这是为了应对Lifecycle 在通知生命周期观察者过程中可能出现的修改LiveData数据的情况(和dispatchingValue 中的援用基本一致)。因为Observer.mActive 是在观察者注册时或者生命周期状态发生改变后通过activeStateChanged 接受消息后才进行更新的。当Lifecycle 进入非活跃状态,遍历所有观察者逐个更新时。如果在完成对LiveData 进行通知前,修改LiveData数据,此时由于LiveData 尚未接收到Lifecycle 生命周期变化的通知,mActive 依旧为true。因此,必须通过主动调用获取Lifecycle 当前最新的状态。下面代码可复现这种场景:

kotlin 复制代码
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    mainViewModel.liveData.observe(this) {
        println("mainViewModel:$it")
    }

    this.lifecycle.addObserver(object : DefaultLifecycleObserver {
        override fun onStop(owner: LifecycleOwner) {
            mainViewModel.liveData.value = 1;
        }
    })

    button.click {
        finish()
    }
}

异步更新

LiveData.postValue 提供了从非主线程中更新数据的能力。其本质上还是通过setValue 更新数据的,只不过是在调用之前增加了Handler线程调度的环节。

ini 复制代码
volatile Object mPendingData = NOT_SET;
static final Object NOT_SET = new Object();
final Object mDataLock = new Object();
private final Runnable mPostValueRunnable = new Runnable() {

    public void run() {
        Object newValue;
        synchronized (mDataLock) {
            newValue = mPendingData;
            mPendingData = NOT_SET;
        }
        setValue((T) newValue);
    }
};
protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

通过 整个异步更新的关键点就在于:通过mPendingData 存储修改后的数据,通过volatile确保其对所有线程可见,保证主线程可以及时拿到其他线程更新后的值。之后通过 ArchTaskExecutor.getInstance().postToMainThread 切回到主线程后读取mPendingData 中的值,调用setValue 更新数据。

LiveData 为��避免不必要的性能开销。在postValue函数中,通过局部变量postTask标记mPendingData 是否发生过修改。当mPendingData 不为空(NOT_SET),则表明当前当前已经存在了未执行完成的流程。或许是高并发下还没执行完postValue,也可能是Handler消息还在队列中尚未分发。 此时就无需重复执行比较消耗新能的线程调度了,只需要修改mPendingData 为最新值。确保mPostValueRunnable 中主线程拿到的mPendingData 值为最新的就行。为了确保并发访问下的线程安全问题。postValue 函数在涉及到mPendingData 的读写通过synchronized 关键字确保线程安全。而由于mPendingData 最终实在主线程中被还原为NOT_SET 的。为了避免mPostValueRunnable 回调中,在mPendingData 恢复初始值的瞬间,有新的线程调用postValue 函数,由此触发线程安全问题,导致最新的数据丢失的问题。因此,LiveData使用同一个对象锁mDataLock,对所有涉及到mPendingData 读写的操作进行加锁,以确保线程安全。这也是为什么mPostValueRunnable 明明是在主线程中执行了,却依旧需要synchronized 的原因。

销毁

参看上文中核心结构小节中的源码示例。使用observe 注册观察者的同时,会增加对观察者所依附的生命周期组件LifecycleOwner 的监听。当监听到LifecycleOwner 处于*DESTROYED 状态时,*LiveData 会自动触发解除和该观察者之间的绑定关系。

而由于observeForever 没有关联任何生命周期组件,所以必须通过手动调用removeObserver 的方式解除监听。

争论

论坛中存在大量的博客在抨击LiveData,其中饱受摧残的当属两个,数据倒灌和多线程下数据丢失。

数据倒灌

所谓数据倒灌发生的场景基本为:Livedata 已经设置过了值之后,再次添加观察者。而这时候,如果观察者处于活跃状态,Livedata 会立刻触发回调给监听者。

数据丢失

观察下面代码的输出结果:

scss 复制代码
liveData.observe(this) {
    println("mainViewModel:$it")
}
for (i in 0..10) {
    Thread {
        liveData.postValue(i)
    }.start()
}
/** 输出结果
* mainViewModel:10
*/

不同线程多次调用了postValue 却只触发了一次数据回调。这就是大家所说的LiveData 多线程操作存在数据丢失问题。其中原理在上文数据更新中的异步更新小节里已经讲过了

但是在抨击之前,一定要清楚**LiveData 的一个设计目的:数据始终保持最新状态**

LiveData 所关注的重点是为观察者提供当前最新的数据,而并不关心数据到底是经过多少次变化。 它并不是为了事件而生的,如果你的程序需要关注每一次数据变化,而不是最新的数据。那么,请选择其他更合适的技术方案。

尾声

最终附上一份代码实践,结合观察者的注册流程,思考并验证下面代码的输出结果:

kotlin 复制代码
class SecondActivity : ComponentActivity() {
    private val mainViewModel: MainViewModel by viewModels()
    private lateinit var button: Button
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        println("onCreate")
        mainViewModel.mutableLiveData1.observe(this) {
            println("onCreate-mutableLiveData1:  $it")
        }
        mainViewModel.mutableLiveData2.observe(this) {
            println("onCreate-mutableLiveData2:  $it")
        }

        for (i in -3..1) {
            mainViewModel.mutableLiveData2.value = i
        }
        button.setOnClickListener {
            println("onClick")
            for (i in 6..7) {
                mainViewModel.mutableLiveData2.value = i
            }
            finish()
        }
    }
    override fun onStart() {
        super.onStart()
        println("onStart")
        mainViewModel.mutableLiveData1.observe(this) {
            println("onStart-mutableLiveData1:  $it")
        }
        mainViewModel.mutableLiveData2.value = 1
    }
    override fun onResume() {
        super.onResume()
        println("onResume")
        mainViewModel.mutableLiveData1.observe(this) {
            println("onResume-mutableLiveData1:  $it")
        }
        mainViewModel.mutableLiveData2.value = 2
    }
    override fun onPause() {
        super.onPause()
        println("onPause")
        mainViewModel.mutableLiveData1.observe(this) {
            println("onPause-mutableLiveData1:  $it")
        }
        mainViewModel.mutableLiveData2.value = 3
    }
    override fun onStop() {
        super.onStop()
        println("onStop")
        mainViewModel.mutableLiveData1.observe(this) {
            println("onStop-mutableLiveData1:  $it")
        }
        mainViewModel.mutableLiveData2.value = 4
    }
    override fun onDestroy() {
        super.onDestroy()
        println("onDestroy")
        mainViewModel.mutableLiveData1.observe(this) {
            println("onDestroy-mutableLiveData1:  $it")
        }
        mainViewModel.mutableLiveData2.value = 5
    }
}


class MainViewModel() : ViewModel() {
    val name = "MainViewModel"
    val mutableLiveData1 = MutableLiveData<Int>()
    val mutableLiveData2 = MutableLiveData<Int>()
    init {
        mutableLiveData1.value = 0
    }
}
相关推荐
ggs_and_ddu22 分钟前
Android--java实现手机亮度控制
android·java·智能手机
zhangphil6 小时前
Android绘图Path基于LinearGradient线性动画渐变,Kotlin(2)
android·kotlin
watl06 小时前
【Android】unzip aar删除冲突classes再zip
android·linux·运维
键盘上的蚂蚁-6 小时前
PHP爬虫类的并发与多线程处理技巧
android
喜欢猪猪7 小时前
Java技术专家视角解读:SQL优化与批处理在大数据处理中的应用及原理
android·python·adb
JasonYin~9 小时前
HarmonyOS NEXT 实战之元服务:静态案例效果---手机查看电量
android·华为·harmonyos
zhangphil9 小时前
Android adb查看某个进程的总线程数
android·adb
抛空9 小时前
Android14 - SystemServer进程的启动与工作流程分析
android
Gerry_Liang11 小时前
记一次 Android 高内存排查
android·性能优化·内存泄露·mat
天天打码13 小时前
ThinkPHP项目如何关闭runtime下Log日志文件记录
android·java·javascript