美文网首页
LiveData解析

LiveData解析

作者: 森码 | 来源:发表于2020-05-28 00:23 被阅读0次

1. 简介

长久以来我们都要去了解Activity或者Fragment的生命周期,因为界面的生命周期是我们处理数据的基础,我们需要知道在哪个地方“才能”去做哪些事,但是这些生命周期又是极其繁琐且样板的,一般来说我们只会去处理几个经常出问题的界面,而选择性的“忽视”一些问题。对于整个App来说,生命周期是一个让人有些不安的概念,因为它总会在不经意间给我们弹出几个bug,无论是稳定性还是数据的完整性,这些不应该是我们在开发业务时关心的事情,我们专注的应该是业务本身而不是被生命周期拖累出的bug,生命周期也应该有一套属于自己的封装。

2. 使用

Livedata

3. 优点

  1. UI和数据保持一致,在数据变更之后自动更新UI。
  2. 数据跟随界面(Activity/Fragment)生命周期,数据在可用时更新,在不可用时销毁,弱化生命周期的概念,同时避免组件在不可用时遭到更改而出现崩溃。
  3. 共享数据,可以在多个Fragmnt中共享数据。

4. 原理

4.1. 前置条件
  1. 理解观察者模式
    观察者模式

  2. 理解LifeCycleEventObserver
    MyLifeCycleEventObserver

理解了上述的两个条件,就能猜想到一大半的实现流程。
我们只要明确两个问题:LiveData是在什么时候去绑定生命周期的?观察者的notify又是什么时候触发的?

4.2. 如何绑定Activity的生命周期

我们在调用LiveData的时候调用的是 LiveDta.observe(LifecycleOwner owner,Observer observer),这个方法里的owner 其实就是AppCompatActivity本身。

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        return;
    }
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    // 存储Observer,便于后面更改值之后分发事件
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    if (existing != null && !existing.isAttachedTo(owner)) {
            不能重复添加
    }
    // 使用wrapper,接收界面生命周期的回调,类似于上文(前置条件)中的MyLifeCycleEventObserver
    owner.getLifecycle().addObserver(wrapper);
}

在我们直接使用LiveData时,它已经不经意间绑定了生命周期,有了生命周期其实我们只要找准时机去触发事件就好了。

4.3. 如何更新(分发)数据

思考:我们想要触发界面的更新,即触发Activity中Observer的onChanged方法,需要在哪里调用?

既然上面说到了LifecycleEventObserver,那么我们很自然的去它的实现类去看一下

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {

    @Override
    boolean shouldBeActive() {
        // 当前生命周期是否在Start之后,包括Start
        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;
        }
        // 这里分两层,shouldBeActive其实就是判断当前生命周期是否在Start之后,其次才是active
        activeStateChanged(shouldBeActive());
    }

    void activeStateChanged(boolean newActive) {
        if (newActive == mActive) {
            return;
        }
        mActive = newActive;
        if (mActive) {
            // 可以理解为观察者的notify方法
            dispatchingValue(this);
        }
    }
}

我们保留最简洁的代码,可以直观的看出:

  • Observer在生命周期到Destroy时反注册自己
  • 在每次Start之后,都会触发更新方法,不过使用了标记位来避免重复的执行
    以上就是生命周期绑定的方法,下面我们分析主动的触发
    @MainThread
    protected void setValue(T value) {
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }

setValue的方法更加简单,设置value并且触发分发,和activeStateChanged方法的处理类似,最终调用的更新方法是相同的dispatchingValue(),只是设置的变量不一样(一个是this,一个是null),这也影响了之后的处理逻辑。

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

在Google的代码里也少不了这样的Flag方法,虽然代码有点啰嗦,但这是一个简单易行的方案。
initiator(发起人、创始者的意思,AndroidX中变量的名字起的是真好)就是Livedata本身,如果有值直接触发这个Livedata的更新,如果没有则触发所有Observer(但不一定都会调用onChanged方法)。

在dispatchingValue方法中最后会调用considerNotify

// 这个confider也起的好,这些notify不是一定会触发,而是要经过慎重思考的。
private void considerNotify(ObserverWrapper observer) {
    if (!observer.mActive) {
        return;
    }
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    // 这个version也是用来减少重复处理的,每次setValue时都会version++
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    // 最后调用Observer的onChanged方法
    observer.mObserver.onChanged((T) mData);
}

5. 总结

LiveData的实现其实不能说是复杂,但是它实现的却很巧妙,简单的使用观察者就能把一直困扰我们的生命周期的问题解决。其实这是一个很好的切入点,我们总是习惯了去做很多事,也许这些事情并不一定需要我们每次都去做,findViewById不是必须的,生命周期的控制不是必须的,数据的设置也不一定是必须的……也许我们应该跳出Android开发的思维,用更省力的角度去解决一些我们已经习以为常的不是问题的问题,也许我们能打开编程的另一扇门。

相关文章

  • LiveData解析

    1. 简介 长久以来我们都要去了解Activity或者Fragment的生命周期,因为界面的生命周期是我们处理数据...

  • LiveData解析

    LiveData is a data holder class that can be observed with...

  • 学习笔记LiveData

    学习下LiveData目录 如何使用 源码解析 粘性事件 1、使用 LiveData是Google的提供标准化开发...

  • Jetpack-LiveData源码解析

    LiveData源码解析 源码版本:2.4.0需会使用:Lifecycle 导航:Jetpack-Lifecycl...

  • ViewModel

    ViewModel生命周期 LiveData,ViewModel,Lifecycle原理解析以及使用 - 简书 (...

  • 从源码看 Jetpack(4)-LiveData衍生

    上篇文章介绍了关于 LiveData 类的源码解析,本篇文章再来介绍下 LiveData 的一系列衍生类及衍生方法...

  • LiveData源码解析

    LiveData 使用最新的 androidx 的源码。 前言 LiveData 是 Android Archit...

  • LiveData源码解析

    0.前言 关于livedata的使用详情见LiveData+ViewModel+RxJava2+autoDispo...

  • LiveData源码解析

    LiveData is a data holder class that can be observed with...

  • LiveData源码解析

    LiveData官方资料Lifecycle官方资料ViewModel官方资料 本文适合对Lifecycle、Liv...

网友评论

      本文标题:LiveData解析

      本文链接:https://www.haomeiwen.com/subject/mjxiahtx.html