Android LiveData原理分析

该文章同步更新到稀土掘金链接

前言

官方介绍:LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
它有以下的优势:

  • 确保界面符合数据状态
  • 不会发生内存泄露
  • 不会因Activity停止而导致崩溃
  • 不再需要手动处理生命周期
  • 数据始终保持最新状态
  • 适当的配置修改
  • 共享资源

接下来我们通过基本使用,一步一步的探究LiveData是如何实现这些优势的。

使用

创建 LiveData 对象
public class CoursePreviewModel extends ViewModel {

    /**
     * view状态
     */
    private MutableLiveData<List<CoursePreviewBean.DataBean>> mStateLiveData;

    public MutableLiveData<List<CoursePreviewBean.DataBean>> viewStateLive() {
        if (mStateLiveData == null) {
            mStateLiveData = new MutableLiveData<>();
        }
        return mStateLiveData;
    }
}
观察 LiveData 对象
class CoursePreviewActivity : AppCompatActivity() {

    // Use the 'by viewModels()' Kotlin property delegate
    // from the activity-ktx artifact
    private val mViewModel: CoursePreviewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 监听
        mViewModel.viewStateLive().observe(this, target -> {
        });
    }
}

原理分析

这里我们先提出几个问题:

  1. LiveData怎么绑定到应用组件的生命周期呢
  2. 为什么不需要我们手动处理生命周期,为什么不会因Activity停止而导致崩溃
  3. 数据变化又是怎么触发的呢

带着这些问题,我们逐步往里看

一、应用组件生命周期的绑定

当我们需要观察数据变化时,需要调用LiveData的observe接口,这也是LiveData与Activity或Fragment产生关联的地方:

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull 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);
    }

这个方法需要接收两个参数:

  • LifecycleOwner:生命周期所有者
  • Observer:观察者,用于观察获取变化后的数据

通常我们在Activity或Fragment中使用LiveData,看下androidx包提供的AppCompatActivity和Fragment都是实现了LifecycleOwner接口。所以直接将this作为第一个参数即可。

继续分析上边的observe方法

  • 这里会首先判断是否在主线程执行,假如不是即会抛出异常
assertMainThread("observe");
static void assertMainThread(String methodName) {
    if (!ArchTaskExecutor.getInstance().isMainThread()) {
        throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
                + " thread");
    }
}
  • 假如是应用组件的生命周期已经是destory的状态,即不会继续往下执行
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
    // ignore
    return;
}
  • 通过LifecycleBoundObserver进行真正的逻辑处理,这里我们继续往下走,待会再回头分析这块
  • 判断相同的observer不能被不同的LifecycleOwner处理
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;
}

这里主要用到SafeIterableMap这个结构保存owner和observer的关系:

// put之前先判断是否已经包含了该key,假如是则直接返回相应的value
public V putIfAbsent(@NonNull K key, @NonNull V v) {
    Entry<K, V> entry = get(key);
    if (entry != null) {
        return entry.mValue;
    }
    put(key, v);
    return null;
}
  • 最后,将生命周期所有者与observer绑定起来,这样子observer即可接收到相应的生命周期
owner.getLifecycle().addObserver(wrapper);

可以看到,这里不是直接add传递进来的Observer,而是上边提到的包装了owner和Observer的LifecycleBoundObserver。所以接下来我们好好分析下它:

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) {
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        activeStateChanged(shouldBeActive());
    }

    @Override
    boolean isAttachedTo(LifecycleOwner owner) {
        return mOwner == owner;
    }

    @Override
    void detachObserver() {
        mOwner.getLifecycle().removeObserver(this);
    }
}

可以看到,LifecycleBoundObserver是实现了LifecycleEventObserver接口,而LifecycleEventObserver接口是继承于LifecycleObserver接口的,因此可以看出主要是在LifecycleBoundObserver这里完成生命周期的处理。

二、为什么不需要手动处理生命周期

经过上边的分析,我们发现其实主要的生命周期处理工作是在LifecycleBoundObserver里边完成的。我们继续看它的源码,有这么两个方法:

    @Override
    public void onStateChanged(@NonNull LifecycleOwner source,
            @NonNull Lifecycle.Event event) {
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        activeStateChanged(shouldBeActive());
    }
    
    @Override
    void detachObserver() {
        mOwner.getLifecycle().removeObserver(this);
    }

我们先看detachObserver,这里明显就是用于解除绑定的。我们找下哪里调用了这个方法:

@MainThread
public void removeObserver(@NonNull final Observer<? super T> observer) {
    assertMainThread("removeObserver");
    ObserverWrapper removed = mObservers.remove(observer);
    if (removed == null) {
        return;
    }
    removed.detachObserver();
    removed.activeStateChanged(false);
}

主要是在LiveData的removeObserver,那继续找下该方法的调用。发现又回到了LifecycleBoundObserver本身,不错就是在onStateChanged里边,它会接收生命周期的变化通知,当发现mOwner.getLifecycle().getCurrentState() == DESTROYED即组件处于destory状态时,自动移除相应的观察者,这样子当activity或fragment销毁时,不会再收到相应的事件通知

三、数据变化怎么触发的

我们继续将核心放在LifecycleBoundObserver的onStateChanged方法上。当组件还没销毁,即会继续往下跑activeStateChanged(shouldBeActive());,该方法定义在ObserverWrapper类里边(LifecycleBoundObserver继承于它)

void activeStateChanged(boolean newActive) {
    if (newActive == mActive) {
        return;
    }
    // immediately set active state, so we'd never dispatch anything to inactive
    // owner
    mActive = newActive;
    boolean wasInactive = LiveData.this.mActiveCount == 0;
    LiveData.this.mActiveCount += mActive ? 1 : -1;
    if (wasInactive && mActive) {
        onActive();
    }
    if (LiveData.this.mActiveCount == 0 && !mActive) {
        onInactive();
    }
    if (mActive) {
        dispatchingValue(this);
    }
}

当处于活跃状态,即mActive为true时,会走到dispatchingValue(this);。我们继续看

void dispatchingValue(@Nullable 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>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

核心在于considerNotify方法

private void considerNotify(ObserverWrapper observer) {
    if (!observer.mActive) {
        return;
    }
    // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
    //
    // we still first check observer.active to keep it as the entrance for events. So even if
    // the observer moved to an active state, if we've not received that event, we better not
    // notify for a more predictable notification order.
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    observer.mObserver.onChanged((T) mData);
}

直接看到最后一句,这里直接调用了observer.mObserver.onChanged((T) mData);,这里就会触发数据变化回调。而这里的mObserver即是我们在刚开始传递进来的。

其他

一、observeForever

其实,LiveData除了提供observe用于方法,还提供了一个observeForever方法

@MainThread
public void observeForever(@NonNull Observer<? super T> observer) {
    assertMainThread("observeForever");
    AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    if (existing instanceof LiveData.LifecycleBoundObserver) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    if (existing != null) {
        return;
    }
    wrapper.activeStateChanged(true);
}

这里可以看到,没有跟生命周期绑定,也不再使用LifecycleBoundObserver进行包装,而是使用AlwaysActiveObserver:

private class AlwaysActiveObserver extends ObserverWrapper {

    AlwaysActiveObserver(Observer<? super T> observer) {
        super(observer);
    }

    @Override
    boolean shouldBeActive() {
        return true;
    }
}

AlwaysActiveObserver和LifecycleBoundObserver都继承于ObserverWrapper,但是前者没有重写它的detachObserver方法,因此它不会被自动移除监听。只能通过手动调用removeObserver进行移除。

二、postValue和setValue

两个方法都可以用于更新值,分析下区别:

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

@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}
  1. setValue必须在主线程调用,否则会抛出异常
  2. postValue用于在其他线程更新值,核心在:ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);,这会切回到主线程执行。
  3. 由于postValue是通过handler的消息派发进行处理,而setValue直接设值,因此这种情况需要注意:
// 源码提示
Posts a task to a main thread to set the given value. So if you have a following code executed in the main thread:
       liveData.postValue("a");
       liveData.setValue("b");
       
The value "b" would be set at first and later the main thread would override it with the value "a".
  1. 如果在主线程执行已发布任务之前多次调用此方法,则只会调度最后一个值。这个是怎么实现的呢?我们看下postValue里边的处理
protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

private final Runnable mPostValueRunnable = new Runnable() {
    @SuppressWarnings("unchecked")
    @Override
    public void run() {
        Object newValue;
        synchronized (mDataLock) {
            newValue = mPendingData;
            mPendingData = NOT_SET;
        }
        setValue((T) newValue);
    }
};

第一次,mPendingData的值为NOT_SET,因此postTask为true,而mPendingData为设置的value。直到mPostValueRunnable被执行时,mPendingData才被重新赋值为NOT_SET。假如在主线程执行前,不断的调用postValue,postTask一直为false,mPendingData会被更新到最新设置的值,但是mPostValueRunnable不会被重复执行。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值