专栏名称: Android技术之家
主要分享Android相关技术文章、移动互联网的相关产品和资讯。关注你将学习到更多基础以及框架相关的知识,为您的工作助力!
目录
相关文章推荐
51好读  ›  专栏  ›  Android技术之家

LiveData取代EventBus?LiveData的通信原理和粘性事件刨析

Android技术之家  · 公众号  ·  · 2021-05-24 07:58

正文

请到「今天看啥」查看全文


LiveData是一个可以在给定生命周期内观察到的数据持有者类。一个观察者可以与一个LifecycleOwner成对地添加,并且只有当配对的LifecycleOwner处于活动状态时,这个观察者才会收到数据变动的通知。

一、LiveData-ViewModel-Repository

以下是LiveData结合ViewModel请求数据的伪代码,这也是JetPack中最常见的一种写法。


ViewModel层:继承ViewModel并创建LiveData,通过postValue将数据发射给UI。


class ExViewModel() : ViewModel() {
    private lateinit var repo: ExRepo
    val liveData: MutableLiveData = MutableLiveData()
    //调用postValue通知UI数据被改变
    fun loadData() = liveData.postValue(repo.loadDataFromRepo())
}

Repository层:从网络或者数据库中请求数据。


class ExRepo() {
    //网络请求或者从数据库中请求
    fun loadDataFromRepo(): String = "网络请求返回的数据"
}


UI层:注册LiveData的观察者,接收数据变化的通知来更新UI。


class ExFragmentFragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val viewModel = ViewModelProviders.of(this).get(ExViewModel::class.java)
        //注册观察者
        viewModel.liveData.observe(thisobject:Observer {
            override fun onChanged(value: String ) {
                   //请求数据成功后,通知UI刷新界面
                   updateUI()
            }
        })

        //请求数据
        viewModel.loadData()
    }
}

上面三层基本上就是一个网络请求的闭环,Repository负责从网络或者数据库中请求数据,ViewModel负责调用Repository的数据,并利用LiveData的 postValue()/setValue() 方法将数据的更新通知到UI层,UI则只需要注册一个LiveData的观察者,当所匹配的LiveData调用 postValue()/setValue() 时,就会收到 onChange() 的通知,去做更新UI的操作。


(此图来源网上)


LiveData遵循观察者模式,它的厉害之处不仅在于数据有变化时能及时通知UI,而且LiveData能够感知Activity、Fragment等组件的生命周期,随组件销毁而自动销毁,不用开发者去操心,极大的减少了内存泄漏的可能。


那LiveData是如何通信并且感知组件的生命周期的呢?

二、LiveData的通信原理

从上面例子可以知道LiveData的核心主要在于这两步, liveData.observe() 以及 liveData.postValue() ,一个是注册观察者,一个是发送通知。那么下面的解析就将这两个函数作为切入点。


1.LiveData.observe()


liveData.observe() 跟踪进去:


 private SafeIterableMapsuper T>, ObserverWrapper> mObservers =
            new SafeIterableMap<>();

            ......

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

observe 方法传有两个参数 LifecycleOwner Observer LifecycleOwner 是一个具有Android生命周期的类,一般传入的是 Activity Fragment Observer 是一个接口,内部存在 void onChanged(T t) 方法。


✅ 第一部分: observe 内部一开始就存在一个生命周期的判断,

if (owner.getLifecycle().getCurrentState() == DESTROYED) {return;}


当组件生命周期已经Destroy了,也就没有必要再继续走下去,则直接return。在这里,LiveData对生命周期的感知也就慢慢显现出来了。


✅ 第二部分: 首先以 LifecycleOwner Observer 作为参数创建了一个 LifecycleBoundObserver 对象,接着以 Observer key ,新创建的 LifecycleBoundObserver value ,存储到mObservers这个map中。在后面LiveData postValue 中会遍历出该map的value值 ObserverWrapper ,获取组件生命周期的状态,以此状态来决定分不分发通知。(这部分详情见“第二小节 postValue() ”)


LifecycleBoundObserver 是什么?


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

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

        .......
    }

从源码可以看到, LifecycleBoundObserver 继承 Observer Wrapper并且实现了 LifecycleEventObserver 的接口, LifecycleEventObserver 是监听组件生命周期更改并将其分派给接收方的一个接口,而在 LifecycleBoundObserver 的构造函数中将 observer 传给了父类 ObserverWrapper


LifecycleBoundObserver 其实只是包裹着 LifecycleOwner Observer 的一个类,其中的实现有点代理模式的味道。


✅ 第三部分: owner.getLifecycle().addObserver(wrapper) 将新创建的 LifecycleBoundObserver 添加到Lifecycle中,也就是说这个时候观察者注册成功,当 LifecycleOwner 也就是组件的状态发生改变时,也会通知到所匹配的 observer


到这里,UI层 viewModel.liveData.observe(this, object:Observer { override fun onChanged(value: String) {} }) 注册观察者的内部解析也就大致清楚了。


2.postValue()


liveData.postValue() 是作为一个发射方来通知数据改变,其内部又做了哪些工作?接下来就一探究竟。直接从 postValue 中最核心的部分在于将参数value赋值给了一个全局变量源码开始:


 protected void postValue(value{
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

postValue 中首先将参数value赋值给了一个全局变量 mPendingData ,它的初始值为一个空对象,而 mPendingData 只是作为一个中间媒介来存储value的值,在后续的操作中会用到,我们就暂时先记住它。


在最后就是一个将线程切换到主线程的操作,主要看 mPostValueRunnable 的实现:


private final Runnable mPostValueRunnable = new Runnable() {
    @SuppressWarnings("unchecked" )
    @Override
    public void run() {
        Object newValue;
        synchronized (mDataLock) {
            newValue = mPendingData;
            mPendingData = NOT_SET;
        }
        setValue((T) newValue);
    }
};

在Runnable中, mPendingData 赋值给了临时变量newValue,最后调用了 setValue() 方法。我们都知道LiveData发送通知可以使用 PostValue 或者 SetValue ,而他两的区别就在于, PostValue 可以在任意线程中调用,而 SetValue 只能在主线程中,因为 PostValue 多了一步上面切换主线程的操作。


OK,接下来就是 PostValue/SetValue 最核心的部分。


@MainThread
protected void setValue(value
{
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(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, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

setValue 中,参数value将值赋给了一个全局变量mData,而这个mData最后将通过 mObserver.onChanged((T) mData); 将需要修改的value值分发给了UI。最后调用传入一个null调用 dispatchingValue 方法。


由于 dispatchingValue 里的参数为null,也就顺理成章的走到了✅ 第二部分。else一进入就是迭代器在遍历 mObservers ,而 mObservers 在第一小节“1. LiveData.observe() ”中说得很清楚,它作为一个map,存储了 Observer ObserverWrapper 。通过遍历,将每个观察者所匹配的 ObserverWrapper 作为参数传给了 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;
        observer.mObserver.onChanged((T) mData);
    }

而在 considerNotify() 中,先通过 observer 来获取组件生命周期的状态,如果处于非活动状态,则拒绝发起通知。在该方法的最后, observer.mObserver.onChanged((T) mData) ,是不是很熟悉,这就是UI层一开始就实现的接口,而就在这找到了最后的发送方。


小结


LiveData是如何通信的?就一句话,UI层注册好一个observer,就存储到一个存储着观察者的map中,直到开发者调用 postValue/setValue 则遍历该map,分发出 observer onChanged 通知,在此过程中,都会监听组件的生命周期,并以此来判断所匹配的组件是否处于活动状态,否则直接return。

三、LiveData的粘性事件


发送消息事件早于注册事件,依然能够接收到消息的通知的为粘性事件


即先调用LiveData的 postValue/setValue 方法,后注册observe,依然能够收到 onChange() 的通知。从上面的分析可以知道,LiveData最后 postValue 是将通知分发给已经注册好的观察者,而LiveData的粘性事件是先发送后注册,那为什么也能够收到通知呢?是哪里分发了 onChange() ?


我们知道粘性事件是注册后就收到了通知,那么就可以以 liveData.observe() 为切入点,看看源码中的实现。


 @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) {
        ......
        owner.getLifecycle().addObserver(wrapper);
    }

LiveData注册观察者,最核心在于 owner.getLifecycle().addObserver(wrapper);addObserver 是用来添加一个 LifecycleObserver ,当 LifecycleOwner 改变状态时,它会被通知。例如,如果 LifecycleOwner 处于 State#STARTED 状态,给定的观察者将收到 Event#ON_CREATE Event#ON_START 事件。


而我们跟踪到它的实现类里面,


public class LifecycleRegistry extends Lifecycle {
......
@Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

        if (previous != null) {
            return;
        }
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            // it is null we should be destroyed. Fallback quickly
            return;
        }

        boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
        State targetState = calculateTargetState(observer);
        mAddingObserverCounter++;
        while ((statefulObserver.mState.compareTo(targetState) 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
            ✅ 切入点
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            popParentState();
            // mState / subling may have been changed recalculate
            targetState = calculateTargetState(observer);
        }

       ......
    }
}

LifecycleRegistry 继承了Lifecycle,是一个处理多个观察者的类,在这个类中的 addObserver 方法有一个被我标记✅切入点。


statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState)) dispatchEvent 表示将 ON_CREATE ON_START 等事件分发给观察者,以达到监听生命周期的作用。在 dispatchEvent 方法中, LifecycleEventObserver 通过 onStateChanged 接口分发给了相应的观察者,如下:


void dispatchEvent(LifecycleOwner owner, Event event{
    State newState = getStateAfter(event);
    mState = min(mState, newState);
    ✅ 切入点
    mLifecycleObserver.onStateChanged(owner, event);
    mState = newState;
}

看到 mLifecycleObserver.onStateChanged(owner, event) 是不是有种熟悉的感觉,其实在第二节源码分析中,类 LifecycleBoundObserver 就实现了 LifecycleEventObserver 接口,并重写了 onStateChanged 方法。


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

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

 ,,,,,,

    @Override
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        ✅ 切入点
        activeStateChanged(shouldBeActive());
    }

 ......
}


如果当前生命周期状态处于DESTROYED,则将观察者从列表中移除,防止内存泄漏,接着就调用了 activeStateChanged 方法。


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


在 ✅ 切入点之前代码不需要多看,只是一些判断当前活动是否活跃的一起逻辑,核心在于 dispatchingValue(this) ,看到这个方法,是不是又感觉到一丝熟悉,如果看了第二节的分析,就会发现第二节 setValue() 中也调用了一句 dispatchingValue(null) ,只不过 setValue 传入的是null,而现在这里传入了一个this值。接下来就来看看传入参数和null有什么不同?


void dispatchingValue(@Nullable ObserverWrapper initiator) {
    ......
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {
            ✅切入点1
            considerNotify(initiator);
            initiator = null;
        } else {
            for (Iterator<Map.Entrysuper T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

因为 dispatchingValue 传入的参数不为null,则逻辑就走进了 ✅切入点1中,接着将initiator作为参数,调用了 considerNotify 方法,这个其实和setValue最后调用的方法是一致的,只是传入的参数不同罢了。 considerNotify 方法中最后将数据发送给了观察者。


private void considerNotify(ObserverWrapper observer) {
    ......
    observer.mObserver.onChanged((T) mData);
}

到此,整个流程也就梳理完成。


小结


LiveData的粘性事件,在于LiveData只要在注册观察者时,就会触发 LifecycleOwner 的状态改变,并且会将 ON_CREATE,ON_START,ON_RESUME 三种状态分发给观察者,而这,就触发了 onChange 的通知。

关注我获取更多知识或者投稿








请到「今天看啥」查看全文