LiveData原理分析

简述

LiveData是一个可被观察的数据容器类,它将数据包装起来,使数据成为被观察者。当数据发生改变时,观察者能够及时得到通知。又是一个典型的观察者模式

ViewModel用来存放页面所需要的数据、和数据相关的处理逻辑(在ViewModel中对数据进行加工、获取),站在页面的角度上,它并不关心ViewModel的业务逻辑,只关心需要展示的数据是啥。它希望在数据发生改变时,能够及时的得到通知并作出更新。而LiveData的作用就是在ViewModel中的数据变化时,去及时的通知页面。因此LiveData通常和ViewModel组合使用。

LiveData原理

首先需要创建一个观察者来观察对象:

//需要一个观察者来观察数据,被观察者有啥举动,观察者这边及时的onChanged作出改变
Observer observer=new Observer<String>(){

    @Override
    public void onChanged(String s) {
        tv.setText(s);
    }
};

然后作出订阅:

//订阅
model.getCurrentName().observe(this,observer);

1.订阅、绑定

通过observe方法进行订阅绑定:

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
  	//判断是否主线程,否则就抛出异常
    assertMainThread("observe");
  	//判断状态,如果DESTORYED就return不管。因为此时Activity没用,根本没必要管
  	//Activity能用,才会继续往下走
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        // ignore
        return;
    }
  	//将观察者、被观察者统一封装到LifecycleBoundObserver中
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
  	//将Observer、LifecycleBoundObserver对象包装放到Entry<Observer,LifecycleBoundObserver对象>中
  	//先get(key)查,有就return返回。没有再put
    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;
    }
  	//调Lifecycle的addObserver方法,用的还是Lifecycle的绑定流程
    owner.getLifecycle().addObserver(wrapper);
}

只有在主线程、且非DESTORYED状态下,才会进行绑定。这里会将观察者、被观察者统一封装到LifecycleBoundObserver对象中,并将Observer对象、LifecycleBoundObserver对象封装到ObserverWrapper对象中。最后调用LifeCycle的addObserver方法,走的还是LifeCycle的绑定流程

2.setValue发送消息

调用的LifeData的setValue方法:

@MainThread
protected void setValue(T value) {
  	//判断是否主线程
    assertMainThread("setValue");
  	//mVersion和mLastVersion呼应
    mVersion++;
    mData = value;
  	//分发Value
    dispatchingValue(null);
}

这里dispatchingValue和ConsiderNotify方法是 “飞雷神互瞬回” :

//第一次调用,传入的null,所以直接走else
void dispatchingValue(@Nullable ObserverWrapper initiator) {
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {
          	//value不为null,直接去发送通知
            considerNotify(initiator);
            initiator = null;
        } else {
          	//迭代器拿到每个观察者Observer
            for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
              	//发通知,当被观察者在setValue(value)时,要发送通知
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

然后开始“互瞬回”了considerNotify:

//关键的3个if
private void considerNotify(ObserverWrapper observer) {
  	//如果Observer不是活动状态,退出
    if (!observer.mActive) {
        return;
    }
    //如果不应该被激活,就进入if
  	//如果当前Activity的最后一个状态,在经历过CompareTo后返回true,即比STARTED大(RESUMED),
  	//就跳过走下一个if
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    observer.mObserver.onChanged((T) mData);
}


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;
  					//用mActiveCount统计有多少个会处于活动状态
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            if (wasInactive && mActive) {
                onActive();
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }
            if (mActive) {
              	//最后“互瞬回”去分发
                dispatchingValue(this);
            }
        }

“飞雷神互瞬回”循环的目的:找到1个正在前台的Activity。关于mVersion和mLastVersion,他们的初始值都是-1。LiveData—>mVersion只有一个(mVersion++),但是Observer—>mLastVersion有多个(mLastVersion=mVersion)。只要setValue一次,就会触发一次mVersion++,Observer.mObserver.onChanged—>最新的一次发消息。considerNotify通知方法的3次if,前2次是判断状态,第3次是判断mVersion和mLastVersion,这是处于性能考虑(一个Thread向Activity发送消息,如果发送60次,但Activity不可见,此时不需要接受处理。当发送第61次时Activity可见,此时接收处理正好)。

LiveData帮我们处理了容错,自己虽然可以实现,但是各种引用满天飞,肯定会内存泄漏。LiveData利用观察者模式,帮我们规避了OOM.

3.总结

LiveData的订阅、绑定,实际上用的还是LifeCycle的绑定流程。使用setValue发送消息,有个很有意思的地方,就是dispatchingValue分发和considerNotify通知的相互调用。分发时首先通过迭代遍历拿到所有的观察者Observer,并发送通知。执行通知方法时会经历3个if判断,不满足条件就又跑回去执行分发了。这样折腾的目的就是为了要找到一个正在前台的Activity,然后执行 observer.mObserver.onChanged((T) mData)方法,这样我们在观察者重写的onChanged方法就会被执行。
LiveData帮我们处理了容错,虽然可以自己实现,但是各种引用满天飞肯定会造成内存泄漏。LiveData利用观察者模式,帮我们完美的规避了这个问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值