Android LiveData实现原理

Posted 进击的包籽

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android LiveData实现原理相关的知识,希望对你有一定的参考价值。

1.了解LiveData

  • Google LiveData 概览
  • LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
  • LiveData本身是观察者,观察组件的Lifecycle,也是被观察者,数据变化时要通知数据的观察者。
  • 可以先了解 Android Lifecycle实现原理,有利于了解LiveData。

2.简单使用

  • 首先在ViewModel 里面添加 MutableLiveData ,一般我们网络请求,或者数据库之类的返回后,如果要发送数据,可以用 postValue ,这个方法会利用Handler切换到主线程再setValue,如果已经在主线程了,就使用普通的 setValue 方法。
class TestViewModel : ViewModel() {

    val  livedata = MutableLiveData<String>("bao")

    init {
        livedata.postValue("bao_post")
    }

    fun initData(){
        livedata.value = "bao_set"
    }
}
    
/* 观察数据变化 */
viewModel.livedata.observe(TestFragment@this, object : Observer<String> {
    override fun onChanged(t: String?) {
        t?.let {
            Log.d(TAG,it)
        }
    }
})

3. 对组件Lifecycle生命周期感知分析

3.1 observe 方法

  • 首先这个方法只能在主线程注册观察。
  • 官方文档说LiveData仅处于活跃生命周期才有效,所以一开始就开始判断是否为 Lifecycle.Stete.DESTROYED,是的话就没有然后了,直接return。
  • 接下来就是 创建 LifecycleBoundObserver ,生命周期变化逻辑在这里面。
  • 然后就是最后一行注册观察,如果想了解 Lifecycle.addObserver 做了什么可以看 Android Lifecycle实现原理
	//map 的 key 为LiveData数据观察者,value为组件的Lifecycle观察者
    private SafeIterableMap<Observer<? super 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;
        }
        //Lifecycle的生命周期变化逻辑在这里
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //mObservers 保存
        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的生命周期变化
        owner.getLifecycle().addObserver(wrapper);
    }

3.2 LifecycleBoundObserver 做了什么

  • LifecycleBoundObserver 继承 ObserverWrapper ,实现 LifecycleEventObserver 接口。
  • ObserverWrapper 用于判断组件当前是否活跃。
  • LifecycleEventObserver 就是 Lifecycle 的观察者了,重写了 onStateChanged 方法,当Lifecycle 生命周期发生变化时,就会在此方法接收到,LiveData 也就能感知到,如果组件的生命周期是 DESTROYED ,那也就移除观察。
  • 到这里 LiveData 对组件的生命周期感知就注册完成了,可以开始发送数据。
    class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
        @NonNull
        //一般组件,比如Activity、fragment可以会实现LifecycleOwner ,可以拿到lifecycle
        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(@NonNull LifecycleOwner source,
                @NonNull Lifecycle.Event event) {
            //获取当前生命周期状态
            Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
            //如果组件已销毁了,就移除观察
            if (currentState == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            Lifecycle.State prevState = null;
            while (prevState != currentState) {
                prevState = currentState;
                activeStateChanged(shouldBeActive());
                currentState = mOwner.getLifecycle().getCurrentState();
            }
        }

		/* 判断是否绑定 */
        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }

		/* 移除观察 */
        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }

3.3 activeStateChanged 方法

  • ObserverWrapper 这个类里面有个方法,后面的粘性事件会用到,先看看。
        void activeStateChanged(boolean newActive) {
        	//组件状态如果不变返回
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive;
            changeActiveCounter(mActive ? 1 : -1);
            //如果是活动的就发送数据
            if (mActive) {
                dispatchingValue(this);
            }
        }

3.4 简易流程图

LiveData注册

4.发送数据分析

4.1 postValue 发送数据到主线程

  • 这个方法最核心的就是利用主线程Handler发送数据,一步步拆开分析,看看他是怎么写的。
    protected void postValue(T value) {
        boolean postTask;
        //加锁
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            //保存要发送的数据value
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        //利用主线程Handler发送
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

4.2 postValue 其实就是 setValue

  • 在postValue 要发送的 Runnable ,可以看到最后一行就是 setValue 方法,数据也即是之前保存的mPendingData ,只是在这又给 newValue。
    private final Runnable mPostValueRunnable = new Runnable() {
        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            setValue((T) newValue);
        }
    };

4.3 postToMainThread 主线程Handler

  • ArchTaskExecutor 类 postToMainThread 方法,实际就是 DefaultTaskExecutor 类执行 postToMainThread 方法。
public class ArchTaskExecutor extends TaskExecutor {
    @NonNull
    private TaskExecutor mDelegate;

    @NonNull
    private TaskExecutor mDefaultTaskExecutor;
    
    private ArchTaskExecutor() {
        mDefaultTaskExecutor = new DefaultTaskExecutor();
        mDelegate = mDefaultTaskExecutor;
    }
	...
    @Override
    public void postToMainThread(Runnable runnable) {
        mDelegate.postToMainThread(runnable);
    }
    ...
}

4.4 DefaultTaskExecutor 类

  • 我们知道是 DefaultTaskExecutor. postToMainThread,就直接看这个方法,哎呀,太熟悉的代码,创建 Handler ,传入的是 Looper.getMainLooper() ,就是主线程Handler ,然后就 post 消息。
  • 如果不了解 Handler ,可以看 Android Handler 从使用到进阶
public class DefaultTaskExecutor extends TaskExecutor {
    @Nullable
    private volatile Handler mMainHandler;

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

4.5 setValue 方法

  • mVersion 在初始化的构造方法里就赋值了,为-1,每次setValue,版本号就会变一次。
  • setValue 也就是用 mData 保存一下 value ,然后交给 dispatchingValue 方法处理。
    @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }

4.6 dispatchingValue 方法

  • setValue走该方法,传的 initiator为空,那就遍历 mObservers 保存的观察者发送数据。
    @SuppressWarnings("WeakerAccess") /* synthetic access */
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
            	//粘性事件,就单个观察者接受数据
                considerNotify(initiator);
                initiator = null;
            } else {
           		//setvalue 传过来 initiator 为空,执行这里
           		// mObservers 拿出来,逐个发送数据
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

4.7 considerNotify 判断发送数据

  • 这里先判断组件是否活动。
  • 在判断粘性事件。
  • 然后用 mVersion ,判断是否发送过数据。
  • 最后才是给观察者发送数据。
    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);
    }

4.8 简易流程图

postValue

5.粘性事件

5.1 粘性事件分析

1.粘性事件就是先发送数据,后面再注册观察者,还能收到消息。
2.我们就从LiveData.observe 开始,新的页面注册LiveData观察者,也注册Lifecycle观察。
3. 当新页面生命周期变化,就会执行 LifecycleBoundObserver.onStateChanged 的方法,如果忘记了回去看 3.2
4. 接下来 activeStateChanged 方法,因为是新页面,组件状态是活动的,就走到 dispatchingValue 方法,看 3.3
5. dispatchingValue 传进来当前新页面的 initiator 是不为空的,就只会给当前观察者发送数据。

5.2 简易流程图

粘性事件

以上是关于Android LiveData实现原理的主要内容,如果未能解决你的问题,请参考以下文章

Android开发——LiveData实现原理

Android LiveData实现原理

Android LiveData实现原理

Android LiveData实现原理

Android-LiveData原理解析

Android MVVM:具有多个片段的活动 - 将共享 LiveData 放在哪里?