美文网首页
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解析

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