Android Jetpack之LiveData源码分析

Android Jetpack之LiveData源码分析

LiveData的使用会结合Lifecycles和ViewModel一起使用,不了解二者的,建议先看这两篇文章:
Android Jetpack之ViewModel源码分析
Android Jetpack之Lifecycles源码分析

LiveData 简介

LiveData 是保存数据对象的类,通过注册监听器Observer 监听数据的变化。LiveData最大的优势:LiveData 是感知Activity、Fragment等生命周期的组件,Observer 可以指定监听的生命周期(Lifecycle)对象。当 Observer 的 Lifecycle 对象处于 STARTED 或者 RESUMED 状态的时候, LiveData 处于活动状态,在活动状态下数据变化会通知到相应的Observer。当相应Lifecycle对象的状态改变为DESTROYED时移除观察者,所以避免造成内存泄漏。当然也可以不和Lifecycles绑定,使用observeForever(Observer)方法注册一个没有关联生命周期所有者对象的观察者,观察者总是处于活动状态,因此数据变化事件总是会被通知到,可以通过调用removeObserver(Observer) 删除observer。
官网指导链接Android jetpack之LiveData

LiveData的简单使用

2.1、创建一个ViewModel类

创建一个ViewModel类,里面有LiveData实例来保存数据。使用ViewModel是为了在屏幕旋转等操作下时可以恢复现场数据。

class MyLiveDataViewModel : ViewModel(){
    var liveData: MutableLiveData<String>?= null
        get() {
            if(field == null){
                field = MutableLiveData()
            }
            return field
        }

}

2.2 创建observer

(1)代码1: 创建LiveDataActivity实现LifecycleOwner接口,为了Observer和组件的生命周期绑定。
(2)代码2: 获取定义的MyLiveDataViewModel实例
(3)代码3: 创建定义onChanged()方法的Observer对象,在数据变化时更新UI页面。
(4)代码4: LiveData订阅观察,将LiveData和Lifecycles、Observer绑定,
(5)代码5: LiveData设置新数据,通知观察者更新数据。可以在子线程中执行。
完整代码如下:

//代码1
class LiveDataActivity : AppCompatActivity(),LifecycleOwner{
    private lateinit var lifecycleRegistroy: LifecycleRegistry
    private var coun : Int by Delegates.notNull<Int>()
    override fun getLifecycle(): Lifecycle {
        return lifecycleRegistroy
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_live_data)
        lifecycleRegistroy = LifecycleRegistry(this)
        coun = 0
        //代码2
        var viewModel = ViewModelProviders.of(this).get(MyLiveDataViewModel::class.java)
        //代码3
        val observer = Observer<String>{
            text.text = it
        }

        button.setOnClickListener {
            //代码5
            viewModel.liveData?.postValue("changed !!!!"+coun++)}
        //代码4
        viewModel.liveData?.observe(this,observer)
    }
}

源码分析

3.1 LiveData.observe方法

在Activity中通过添加observe方法将Lifecycles和Observer绑定起来。下面我们来分析该方法。该方法有两个参数:

  1. LifecycleOwner是为了处理生命周期改变。
  2. Observer是为了监听LiveData的数据变化的观察者。

下面来分析observe方法内部的实现原理:

  1. 在observe方法内部判断了Lifecycler的当前状态,如果State处于DESTROYED,即观察者处于DESTROYED状态时,不做任何处理。
  2. 如果处于活跃状态,则创建LifecycleBoundObserver实例保存传入的LifecycleOwner和Observer,并保存在mObservers中。SafeIterableMap存储的是键值对的形式,使用的是SafeIterableMap数据结构,不熟悉的可以参考Android Jectpack之Lifecycles源码分析。KEY是Observer,VALUE是LifecycleBoundObserver类。
  3. 如果Observer对象已经存在对应的Lifecycles则抛出异常。
  4. 为LifecycleOwner添加生命周期的观察者,其实就是LifecycleBoundObserver类,该类实现了GenericLifecycleObserver接口,可以通过onStateChanged方法监听LifecycleOwner的State变化。
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);
    }

3.2 LifecycleBoundObserver类

3.2.1 LifecycleBoundObserver类

通过observe.observer的分析我们知道,内部主要是用了LifecycleBoundObserver类,下面分析该类

  1. LifecycleBoundObserver 继承自 ObserverWrapper 而且实现 GenericLifecycleObserver接口,而 GenericLifecycleObserver 接口又继承自 LifecycleObserver 接口。在Lifecycles的源码分析我们知道,实现了LifecycleObserver接口而且 LifecycleOwner 的观察者里可以获取 LifecycleOwner 的状态。
  2. shouldBeActive方法表示只有STARTED,RESUMED才是活跃状态
  3. 当Lifecycles的State发生变化会回调onStateChanged方法,当State为DESTROYED是,则移除观察气Observer。里面调用的是LiveData的removeObserver方法(下面会分析)。
  4. 当State非DESTROYED,则调用ObserverWrapper的activeStateChanged方法。
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
        @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(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);
        }
    }

3.2.2 ObserverWrapper类

LifecycleBoundObserver 继承自 ObserverWrapper并且在onStateChanged中调用了activeStateChanged的方法,下面来分析一下ObserverWrapper类。

  1. ObserverWrapper 在LifecycleOwner活跃状态改变时回调onActive和onInactive方法。Owner为活跃状态时回调onActive() ,当Owner未活跃状态时回调onInactive()
  2. 当状态变为活跃态是,LiveData.this.mActiveCount加1
  3. 当变成活跃态时,会执行dispatchingValue方法,通知Observer并发送最新的数据。(源码分析在下一节)
  4. onActive() :当 LiveData 具有活动状态的 Observer 的时候会调用这个函数。当我们自定义LiveData时,可以在这个函数中处理自己的业务逻辑
  5. onInactive():当 LiveData 没有活动状态的 Observer 的时候会调用这个函数。当我们自定义LiveData时,可以在这个函数中处理自己的业务逻辑,不如一些非后台的操作或者变量的释放。
private abstract class ObserverWrapper {
        final Observer<? super T> mObserver;
        boolean mActive;
        int mLastVersion = START_VERSION;

        ObserverWrapper(Observer<? super T> observer) {
            mObserver = observer;
        }

        abstract boolean shouldBeActive();

        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }

        void detachObserver() {
        }

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

3.2.3 AlwaysActiveObserver类

使用observeForever(Observer)方法注册一个没有关联生命周期所有者对象的观察者,观察者总是处于活动状态,因此数据变化事件总是会被通知到。下面我们来看一下其中的原理:

public void observeForever(@NonNull Observer<? super T> observer) {
        assertMainThread("observeForever");
        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);
    }

在observeForever使用的AlwaysActiveObserver该类不同于LifecycleBoundObserver类,没有实现GenericLifecycleObserver接口,所以不能感激组件的生命周期变化,并且其实该方法,也没有LifecycleOwner的形参。在AlwaysActiveObserver 的类内部的shouldBeActive方法用于返回ture,并且在observeForever内部将ObserverWrapper.mActive设置为true,也就是标明永远是处于活跃状态,所以Observer是一直可以观察数据变化的。

 private class AlwaysActiveObserver extends ObserverWrapper {

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

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

3.3 LiveData类

在Activity中,通过postValue或者setValue改变LivwData的数据,在通过Observer,观察LIveData数据的变化。通过上面的分析,我们已经知道了Observer是如何和组件的生命周期绑定起来的,下面我们就分析一下,LiveData的数据更新是如何通知到Observer 的。

3.3.1 setValue方法

先来分析一下setValue()方法,setValue()必须在主线程中调用,否则会报错,而postValue则没有这个检查。看到有无post的区别,第一反应就是是invalidate和postInvalidate的区别。

   protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }
  1. 调用assertMainThread()检查是否在主线程。
  2. 把更新的数据赋给mData。
  3. 调用 dispatchingValue()方法并传入null,将数据分发给所有观察者。dispatchingValue如果传入null则是所有的观察者,如果是具体的ObserverWrapper对象,则通知到具体的Observer。

3.3.2 dispatchingValue方法

下面在分析一下dispatchingValue方法。

  1. dispatchingValue参数传null将会通知所有的观察者,
  2. dispatchingValue不传null只会通知传入的观察者。
  3. 在代码1处,通过遍历 mObservers ,将所有的 LifecycleBoundObserver 取出,对每个观察者调用considerNotify()方法,considerNotify方法就是真正通知到观察者的代码了。
void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
               //代码1
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

3.3.4 considerNotify方法

  1. 如果ObserverWrapper的状态为非活跃态则直接返回。这就验证了只有STARTED、RESUMED才能接受数据的结论
  2. considerNotify方法中调用mObserver的onChange方法,从而通知Observer更新数据。
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
        observer.mObserver.onChanged((T) mData);
    }

3.3.5 postValue方法

postValue方法可以在非主线程中更新数据。主要是通过ArchTaskExecutor和DefaultTaskExecutor切换到主线程中。然后回调到Runnable方法中,在Runnable的run方法其实也是调用了setValue方法来实现通知观察者更新数据的逻辑的。

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() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //noinspection unchecked
            setValue((T) newValue);
        }
    };

3.3.6 ArchTaskExecutor类

ArchTaskExecutor是单例模式。继承自TaskExecutor。

public static ArchTaskExecutor getInstance() {
        if (sInstance != null) {
            return sInstance;
        }
        synchronized (ArchTaskExecutor.class) {
            if (sInstance == null) {
                sInstance = new ArchTaskExecutor();
            }
        }
        return sInstance;
    }

当调用postToMainThread切换线程是,内部实际上是执行了DefaultTaskExecutor类的postToMainThread方法。

public void postToMainThread(Runnable runnable) {
        mDelegate.postToMainThread(runnable);
    }

DefaultTaskExecutor类的postToMainThread内部通过Handler实现线程的切换。

@Override
    public void postToMainThread(Runnable runnable) {
        if (mMainHandler == null) {
            synchronized (mLock) {
                if (mMainHandler == null) {
                    mMainHandler = new Handler(Looper.getMainLooper());
                }
            }
        }
        //noinspection ConstantConditions
        mMainHandler.post(runnable);
    }

3.4 小结

  1. 使用LifecycleOwner的observe() 方法将观察者对象附加到LiveData对象,将观察者向LiveData对象订阅,以便通知LiveData中数据的变化。
  2. 当Lifecycle 没有处于活动状态( (STARTED 、RESUMED)),Observer 则不会被通知,即使数据发生了变化,没有处于活动状态的 Observer 也不会被通知。
  3. Lifecycle 被销毁(destroyed)Observer 也自动被删除,无需用户手动清理。
  4. 避免内存泄漏:Observer 和 Lifecycle 绑定,可以感知组件生命周期,所以当 Lifecycle 被销毁后,Observer 自动被remove避免内粗泄漏。

LiveData高阶使用

4.1 转换LiveData

LiveData 支持简单的数据变换。

  1. map 是把一个数据类型变换为另外一个数据类型。
  2. switchMap 是把一个数据变化为另外一个 LiveData

使用 Transformation 的好处:如果 Lifecycle 处于未激活状态,则转换函数也同样不会执行。
map实例:

class MyLiveDataViewModel : ViewModel(){
    var liveData: MutableLiveData<User> = MutableLiveData()
        get() {
            return field
        }

}

class User(val name: String,val lastName: String)


class LiveDataActivity : AppCompatActivity(),LifecycleOwner{
    private lateinit var lifecycleRegistroy: LifecycleRegistry
    override fun getLifecycle(): Lifecycle {
        return lifecycleRegistroy
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_live_data)
        lifecycleRegistroy = LifecycleRegistry(this)
        var viewModel = ViewModelProviders.of(this).get(MyLiveDataViewModel::class.java)

        val observer = Observer<String>{
            text.text = it
        }

        button.setOnClickListener {
            var user = User("android","jectpack")
            viewModel.liveData.postValue(user)}

        val userLivaData: LiveData<User> = viewModel.liveData
        val nameLiveData: LiveData<String> = Transformations.map(userLivaData){
            it.name + it.lastName
        }
        nameLiveData.observe(this,observer)
    }
}

switchMap实例:

class LiveDataActivity : AppCompatActivity(),LifecycleOwner{
    private lateinit var lifecycleRegistroy: LifecycleRegistry
    override fun getLifecycle(): Lifecycle {
        return lifecycleRegistroy
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_live_data)
        lifecycleRegistroy = LifecycleRegistry(this)
        var viewModel = ViewModelProviders.of(this).get(MyLiveDataViewModel::class.java)

        val observer = Observer<String>{
            text.text = it
        }

        button.setOnClickListener {
            var user = User("android","jectpack")
            viewModel.liveData.postValue(user)}

        val userLivaData: LiveData<User> = viewModel.liveData
        val nameLiveData: LiveData<String> = Transformations.switchMap(userLivaData){
            getUserName(it)
        }
        nameLiveData.observe(this,observer)
    }
    private fun getUserName(user: User): LiveData<String> {
        val liveData: MutableLiveData<String> = MutableLiveData<String>()
        liveData.value = user.name +" switch map " + user.lastName
        return liveData
    }
}

4.2 MediatorLiveData

MediatorLiveData的作用是合并几个流到一个流中。
实例代码:

class LiveDataActivity : AppCompatActivity(),LifecycleOwner{
    private lateinit var lifecycleRegistroy: LifecycleRegistry
    override fun getLifecycle(): Lifecycle {
        return lifecycleRegistroy
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_live_data)
        lifecycleRegistroy = LifecycleRegistry(this)
        var viewModel = ViewModelProviders.of(this).get(MyLiveDataViewModel::class.java)

        val observer = Observer<String>{
            text.text = it
        }

        button.setOnClickListener {
            var user = User("android","jectpack")
            viewModel.liveData.postValue(user)}

        val userLivaData: LiveData<User> = viewModel.liveData
        val nameLiveData: LiveData<String> = Transformations.switchMap(userLivaData){
            getUserName(it)
        }
        var mediatorLiveData: MediatorLiveData<String> = MediatorLiveData()
        mediatorLiveData.addSource(userLivaData){
            mediatorLiveData.value = "first source "
        }
        mediatorLiveData.addSource(nameLiveData){
            mediatorLiveData.value = it + " second source"
        }

        mediatorLiveData.observe(this,observer)
    }
    private fun getUserName(user: User): LiveData<String> {
        val liveData: MutableLiveData<String> = MutableLiveData<String>()
        liveData.value = "  "
        return liveData
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容