资讯专栏INFORMATION COLUMN

Android livedata 源码解剖

GHOST_349178 / 545人阅读

摘要:方法中,,当为,并且不等于上一次的值,会增加的计数。锁住当前没有人在处理任务处理完毕之后将置为首先,采用同步机制,通过有没有人在处理任务。

说在前面

本次推出 Android Architecture Components 系列文章,目前写好了四篇,主要是关于 lifecycle,livedata 的使用和源码分析,其余的 Navigation, Paging library,Room,WorkMannager 等春节结束之后会更新,欢迎关注我的公众号,有更新的话会第一时间会在公众号上面通知。

Android lifecycle 使用详解

Android LiveData 使用详解

Android lifecyle 源码解剖

Android livedata 源码解剖

github sample 地址: ArchiteComponentsSample

Android 技术人,一位不羁的码农。


前言

在前面三篇博客中,我们已经介绍了 lifecycle 的使用及原理,livedata ,ViewModel 的常用用法,今天,让我们一起来学习 livedata 的原理。

我们先来回顾一下 LiveData 的特点:

LiveData 是一个可以被观察的数据持有类,它可以感知 Activity、Fragment或Service 等组件的生命周期。

    它可以做到在组件处于激活状态的时候才会回调相应的方法,从而刷新相应的 UI。

    不用担心发生内存泄漏

    当 config 导致 activity 重新创建的时候,不需要手动取处理数据的储存和恢复。内部已经帮我们封装好了。

    当 Actiivty 不是处于激活状态的时候,如果你想 livedata setValue 之后立即回调 obsever 的 onChange 方法,而不是等到 Activity 处于激活状态的时候才回调 obsever 的 onChange 方法,你可以使用 observeForever 方法,但是你必须在 onDestroy 的时候 removeObserver

下面,让我们一步步解剖它


原理分析

我们知道 livedata 的使用很简单,它是采用观察者模式实现的

    添加观察者

    在数据改变的时候设置 value,这样会回调 Observer 的 onChanged 方法

MutableLiveData<String> nameEvent = mTestViewModel.getNameEvent();
nameEvent.observe(this, new Observer<String>() {
    @Override
    public void onChanged(@Nullable String s) {
        Log.i(TAG, "onChanged: s = " + s);
        mTvName.setText(s);
    }
});
observe 方法
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
    // 判断是否已经销毁
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        // ignore
        return;
    }
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
	// observer 已经添加过了,并且缓存的 observer 跟 owner 的 observer 不一致,状态异常,抛出异常
    if (existing != null && !existing.isAttachedTo(owner)) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
	// 已经添加过 Observer 了,返回回去
    if (existing != null) {
        return;
    }
	
	// 添加 observer
    owner.getLifecycle().addObserver(wrapper);
}

首先,我们先来看一下它的 observe 方法,首先通过 owner.getLifecycle().getCurrentState() 获取状态,判断是否已经被销毁,如果已经被销毁,直接返回。接着用 LifecycleBoundObserver 包装起来。然后从缓存的 mObservers 中读取 observer,如果有,证明已经添加过了。

observe 方法,小结起来就是

    判断是否已经销毁,如果销毁,直接移除

    用 LifecycleBoundObserver 包装传递进来的 observer

    是否已经添加过,添加过,直接返回

    将包装后的 LifecycleBoundObserver 添加进去

因此,当 owner 你(Activity 或者 fragment) 生命周期变化的时候,会回调 LifecycleBoundObserver 的 onStateChanged 方法,onStateChanged 方法又会回调 observer 的 onChange 方法

LifecycleBoundObserver
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
    @NonNull final LifecycleOwner mOwner;

    LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer observer) {
        super(observer);
        mOwner = owner;
    }

    @Override
    boolean shouldBeActive() {
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }

    @Override
    public void onStateChanged(LifecycleOwner source, 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,继承 ObserverWrapper,实现了 GenericLifecycleObserver 接口。而 GenericLifecycleObserver 接口又实现了 LifecycleObserver 接口。 它包装了我们外部的 observer,有点类似于代理模式。

GenericLifecycleObserver#onStateChanged

Activity 回调周期变化的时候,会回调 onStateChanged ,会先判断 mOwner.getLifecycle().getCurrentState() 是否已经 destroy 了,如果。已经 destroy,直接移除观察者。这也就是为什么我们不需要手动 remove observer 的原因

如果不是销毁状态,会调用 activeStateChanged 方法 ,携带的参数为 shouldBeActive() 返回的值。 而当 lifecycle 的 state 为 started 或者 resume 的时候,shouldBeActive 方法的返回值为 true,即表示激活。

	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);
    }

}

activeStateChanged 方法中,,当 newActive 为 true,并且不等于上一次的值,会增加 LiveData 的 mActiveCount 计数。接着可以看到,onActive 会在 mActiveCount 为 1 时触发,onInactive 方法则只会在 mActiveCount 为 0 时触发。即回调 onActive 方法的时候活跃的 observer 恰好为 1,回调 onInactive 方法的时候,没有一个 Observer 处于激活状态。

当 mActive 为 true 时,会促发 dispatchingValue 方法。

dispatchingValue

private void dispatchingValue(@Nullable ObserverWrapper initiator) {
   // 如果正在处理,直接返回
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
	
    do {
        mDispatchInvalidated = false;
		// initiator 不为 null,调用 considerNotify 方法
        if (initiator != null) {
            considerNotify(initiator);
            initiator = null;
        } else { // 为 null 的时候,遍历所有的 obsever,进行分发
            for (Iterator, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
	// 分发完成,设置为 false
    mDispatchingValue = false;
}

其中 mDispatchingValue, mDispatchInvalidated 只在 dispatchingValue 方法中使用,显然这两个变量是为了防止重复分发相同的内容。当 initiator 不为 null,只处理当前 observer,为 null 的时候,遍历所有的 obsever,进行分发

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;
    //noinspection unchecked
	// 调用外部的 mObserver 的 onChange 方法
    observer.mObserver.onChanged((T) mData);
}

    如果状态不是在活跃中,直接返回,这也就是为什么当我们的 Activity 处于 onPause, onStop, onDestroy 的时候,不会回调 observer 的 onChange 方法的原因。

    判断数据是否是最新,如果是最新,返回,不处理

    数据不是最新,回调 mObserver.onChanged 方法。并将 mData 传递过去

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

setValue 方法中,首先,断言是主线程,接着 mVersion + 1; 并将 value 赋值给 mData,接着调用 dispatchingValue 方法。dispatchingValue 传递 null,代表处理所有 的 observer。

这个时候如果我们依附的 activity 处于 onPause 或者 onStop 的时候,虽然在 dispatchingValue 方法中直接返回,不会调用 observer 的 onChange 方法。但是当所依附的 activity 重新回到前台的时候,会促发 LifecycleBoundObserver onStateChange 方法,onStateChange 又会调用 dispatchingValue 方法,在该方法中,因为 mLastVersion < mVersion。所以会回调 obsever 的 onChange 方法,这也就是 LiveData 设计得比较巧妙的一个地方

同理,当 activity 处于后台的时候,您多次调用 livedata 的 setValue 方法,最终只会回调 livedata observer 的 onChange 方法一次。

postValue
protected void postValue(T value) {
   boolean postTask;
   // 锁住
   synchronized (mDataLock) {
      // 当前没有人在处理 post 任务
       postTask = mPendingData == NOT_SET;
       mPendingData = value;
   }
   if (!postTask) {
       return;
   }
   AppToolkitTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
private final Runnable mPostValueRunnable = new Runnable() {
   @Override
   public void run() {
       Object newValue;
       synchronized (mDataLock) {
           newValue = mPendingData;
		   // 处理完毕之后将 mPendingData 置为 NOT_SET
           mPendingData = NOT_SET;
       }
       //noinspection unchecked
       setValue((T) newValue);
   }
};

    首先,采用同步机制,通过 postTask = mPendingData == NOT_SET 有没有人在处理任务。 true,没人在处理任务, false ,有人在处理任务,有人在处理任务的话,直接返回

    调用 AppToolkitTaskExecutor.getInstance().postToMainThread 到主线程执行 mPostValueRunnable 任务。

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

private class AlwaysActiveObserver extends ObserverWrapper {

    AlwaysActiveObserver(Observer observer) {
        super(observer);
    }

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

因为 AlwaysActiveObserver 没有实现 GenericLifecycleObserver 方法接口,所以在 Activity o生命周期变化的时候,不会回调 onStateChange 方法。从而也不会主动 remove 掉 observer。因为我们的 obsever 被 remove 掉是依赖于 Activity 生命周期变化的时候,回调 GenericLifecycleObserver 的 onStateChange 方法。


总结

    liveData 当我们 addObserver 的时候,会用 LifecycleBoundObserver 包装 observer,而 LifecycleBoundObserver 可以感应生命周期,当 activity 生命周期变化的时候,如果不是处于激活状态,判断是否需要 remove 生命周期,需要 remove,不需要,直接返回

    当处于激活状态的时候,会判断是不是 mVersion最新版本,不是的话需要将上一次缓存的数据通知相应的 observer,并将 mLastVsersion 置为最新

    当我们调用 setValue 的时候,mVersion +1,如果处于激活状态,直接处理,如果不是处理激活状态,返回,等到下次处于激活状态的时候,在进行相应的处理

    如果你想 livedata setValue 之后立即回调数据,而不是等到生命周期变化的时候才回调数据,你可以使用 observeForever 方法,但是你必须在 onDestroy 的时候 removeObserver。因为 AlwaysActiveObserver 没有实现 GenericLifecycleObserver 接口,不能感应生命周期。

题外话

Android Architecture Components 已经写了四篇文章了,其余的 Navigation, Paging library,Room,WorkMannager 等春节结束之后再更新了,欢迎关注我的公众号,有更新的话会第一时间在公众好上面更新。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/7271.html

相关文章

  • Android lifecyle 源码解剖

    摘要:使用详解使用详解源码解剖源码解剖地址技术人,一位不羁的码农。在中,它默认为我们初始化,作为一个成员变量。在方法中,它会判断我们是否已经添加,没有的话,添加进去。说在前面 本次推出 Android Architecture Components 系列文章,目前写好了四篇,主要是关于 lifecycle,livedata 的使用和源码分析,其余的 Navigation, Paging libr...

    番茄西红柿 评论0 收藏0
  • 改造 Android 官方架构组件 ViewModel

    摘要:前言官方架构组件在今年月份大会上被公布直到月份一直都是测试版由于工作比较繁忙期间我只是看过类似的文章但没有在实际项目中使用过更没有看过源码所以对这几个组件的使用很是生疏同时也觉得这几个组件非常高大上非常神秘直到月份官方架构组件正式版发布并且 前言 Android 官方架构组件在今年 5 月份 Google I/O 大会上被公布, 直到 11 月份一直都是测试版, 由于工作比较繁忙, 期...

    DevTTL 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<