美文网首页Android Jetpack
Jetpack系列-LiveData使用和源码分析

Jetpack系列-LiveData使用和源码分析

作者: 木水Code | 来源:发表于2022-05-10 09:51 被阅读0次

    1 简介和简单使用

    1.1 简介

    LiveData是一种可观察的数据存储器类。与常规的可观察类不同,LiveData具有生命周期感知能力,意指它遵循其他应用组件(如Activity、Fragment或Service)的生命周期。这种感知能力可确保LiveData仅更新处于活跃生命周期(onStart、onResume)状态的应用组件观察者。LiveData通常和ViewModel相结合使用。

    LiveData依赖于Lifecycle,需要使用Lifecycle提供的状态来判断程序的活跃状态。

    如果观察者(由Observer类表示)的生命周期处于STARTED或RESUMED状态,则LiveData会认为该观察者处于活跃状态。LiveData 只会将更新通知给活跃的观察者。为观察LiveData对象而注册的非活跃观察者不会收到更改通知。

    Google官网:https://developer.android.google.cn/topic/libraries/architecture/livedata?hl=zh_cn

    1.2 简单使用

    引入依赖,按需所取。

    def lifecycle_version = "2.4.1"
    def arch_version = "2.1.0"
    
    // ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    // LiveData
    implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
    // Lifecycles only (without ViewModel or LiveData)
    implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
    
    // Saved state module for ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
    
    // Annotation processor
    annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
    // alternately - if using Java8, use the following instead of lifecycle-compiler
    implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
    
    // optional - helpers for implementing LifecycleOwner in a Service
    implementation "androidx.lifecycle:lifecycle-service:$lifecycle_version"
    
    // optional - ProcessLifecycleOwner provides a lifecycle for the whole application process
    implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
    
    // optional - ReactiveStreams support for LiveData
    implementation "androidx.lifecycle:lifecycle-reactivestreams:$lifecycle_version"
    
    // optional - Test helpers for LiveData
    testImplementation "androidx.arch.core:core-testing:$arch_version"
    

    创建一个单例StrLiveData,里边会实例化一个MutableLiveData,用来存储String类型的数据。

    object StrLiveData {
        //懒加载
        val info: MutableLiveData<String> by lazy { MutableLiveData() }
    }
    

    在Activity中使用。

    class LiveDataActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_live_data)
    
            val tvContent = findViewById<TextView>(R.id.tv_content)
    
            //观察数据变化,界面可见时,才会给TextView设置数据
            StrLiveData.info.observe(this) {
                tvContent.text = it
            }
    
            //观察数据变化,不管界面可见不可见,都给TextView设置数据
            //observeForever不会考虑生命周期,任何状态下都会执行
            StrLiveData.info.observeForever {
                tvContent.text = it
            }
    
            //主线程修改数据
            StrLiveData.info.value = "在主线程修改的数据"
    
            thread {
                Thread.sleep(2000)
                //子线程修改数据
                StrLiveData.info.postValue("在子线程修改的数据")
            }
        }
    }
    

    XML文件。

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"
        tools:context=".jetpack.livedata.demo1.LiveDataActivity">
    
        <TextView
            android:id="@+id/tv_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
    </LinearLayout>
    

    1.3 关系框架

    2 源码分析

    2.1 setValue 主线程修改数据

    首先在业务层单例中实例化了一个MutableLiveData,MutableLiveData继承LiveData,只保留setValue和postValue两个设置数据的方法,简化使用。

    public class MutableLiveData<T> extends LiveData<T> {
    
        /**
         * Creates a MutableLiveData initialized with the given {@code value}.
         *
         * @param value initial value
         */
        public MutableLiveData(T value) {
            super(value);
        }
    
        /**
         * Creates a MutableLiveData with no value assigned to it.
         */
        public MutableLiveData() {
            super();
        }
    
        @Override
        public void postValue(T value) {
            super.postValue(value);
        }
    
        @Override
        public void setValue(T value) {
            super.setValue(value);
        }
    }
    

    当业务层调用LiveData的setValue方法时,在主线程修改数据。

    //主线程修改数据
    StrLiveData.info.value = "在主线程修改的数据"</pre>
    
    setValue方法首先会检查当前是否是主线程,然后会对mVersion+1,接着分发数据。
    
    <pre data-language="java" id="QU8SA" class="ne-codeblock language-java" style="border: 1px solid #e8e8e8; border-radius: 2px; background: #f9f9f9; padding: 16px; font-size: 13px; color: #595959">@MainThread
    protected void setValue(T value) {
        //检查是否是主线程
        assertMainThread("setValue");
        //mVersion+1
        mVersion++;
        mData = value;
        //分发数据
        dispatchingValue(null);
    }
    

    mVersion是LiveData粘性数据特性的关键,它的初始值是-1。

    static final int START_VERSION = -1;
    
    public LiveData() {
         mData = NOT_SET;
         //LiveData实例化的时候给mVersion赋值为-1
         mVersion = START_VERSION;
    }
    

    分发数据的时候有两种情况,一种是调用LiveData.observe(),另一种是调用LiveData.observeForever()。ObserverWrapper是观察者的包装类。

    void dispatchingValue(@Nullable ObserverWrapper initiator) {
            ...
            //initiator(观察者)不为空
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                //initiator(观察者)为空,需要遍历所有的观察者
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                     mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
           ...
    }
    

    接下来调用considerNotify方法。然后对当前是否是活跃状态进行检查,也就是mActive是否为true。为true才会继续执行。就这对mVersion进行对比,由于在setValue的时候mVersion++之后变为0,mLastVersion为-1,所以这里observer.mLastVersion >= mVersion不成立,数据会正常分发出去,这就是造成粘性数据特征的原因。

    如果调用LiveData.observe(),那么当Lifecycle状态为STARTED和RESUMED,也就是Activity/Fragment生命周期为onStart和onResume的时候,mActive=true,其他状态和生命周期下,mActive=fale;如果调用LiveData.observeForever(),mActive一直为true,这就实现了调用LiveData.observeForever()时候,观察者不会去考虑生命周期和状态,所有数据都会无条件感知。

    private void considerNotify(ObserverWrapper observer) {
            if (!observer.mActive) {
                return;
            }
            //判断mActivie是否为true。
            //调用LiveData.observe()时会根据状态和生命周期计算mActive的值;
            //调用LiveData.observeForever()时mActive一直为true。
            if (!observer.shouldBeActive()) {
                observer.activeStateChanged(false);
                return;
            }
            //判断mVersion
            if (observer.mLastVersion >= mVersion) {
                return;
            }
            observer.mLastVersion = mVersion;
            //回调数据给观察者
            observer.mObserver.onChanged((T) mData);
    }
    

    2.2 postValue 子线程修改数据

    当业务层调用LiveData的postValue方法时,在子线程修改数据。

    thread {
        ...
        //子线程修改数据
        StrLiveData.info.postValue("在子线程修改的数据")
    }
    

    postValue方法中最终也会通过Handler切换到主线程。

    protected void postValue(T value) {
        boolean postTask;
        //加锁,防止线程安全问题
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        //切换到主线程
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }
    

    在ArchTaskExecutor中,会实例化一个DefaultTaskExecutor,然后调用DefaultTaskExecutor的postToMainThread方法。

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

    DefaultTaskExecutor使用Handler进行线程间通信,实现子线程到主线程切换。

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

    而在postToMainThread中传入的Runnable中,最红也调用了setValue,接下来的逻辑就和主线程中修改数据一致了。

    private final Runnable mPostValueRunnable = new Runnable() {
        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //最终也是调用setValue
            setValue((T) newValue);
        }
    };
    

    2.3 observe 根据生命周期感知数据变化

    调用LiveData的observe( LifecycleOwner owner, Observer<? super T> observer)方法时,传入了一个被观察者和观察者。

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        //检查是否是主线程
        assertMainThread("observe");
        //获取Lifecycle当前状态,如果是销毁状态,那就忽略,不再继续往下进行
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            return;
        }
        //创建一个LifecycleBoundObserver对象,包装了LifecycleOwner和Observer。
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //ObserverWrapper包装了LifecycleBoundObserver和Observer
        //把Observer和LifecycleBoundObserver存入map
        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);
    }
    

    LifecycleBoundObserver是LiveData的内部类,继承了ObserverWrapper,并且实现LifecycleObserver。传入了一个被观察者和观察者。

    class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
        @NonNull
        final LifecycleOwner mOwner;
    
        //传入被观察者和观察者
        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
            super(observer);
            mOwner = owner;
        }
    
        @Override
        boolean shouldBeActive() {
            //从Lifecycle获取到当前是否是活跃状态(UI可见状态)。
            //Activity/Fragment生命周期onStart和onResume,Lifecycle对应状态为STARTED和RESUMED时,处于活跃状态。
            //这里使用了一个比较,也就是状态在STARTED和STARTED之后时,就处于活跃状态。
            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;
                //调用ObserverWrapper的activeStateChanged,再调用dispatchingValue分发数据。
                activeStateChanged(shouldBeActive());
                currentState = mOwner.getLifecycle().getCurrentState();
            }
        }
    
        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }
    
        @Override
        void detachObserver() {
            //观察者和被观察者解除绑定
            mOwner.getLifecycle().removeObserver(this);
        }
    }
    

    ObserverWrapper是LiveData的抽象内部类。

    private abstract class ObserverWrapper {
        final Observer<? super T> mObserver;
        boolean mActive;
        int mLastVersion = START_VERSION;
    
        ObserverWrapper(Observer<? super T> observer) {
            mObserver = observer;
        }
    
        //抽象方法,判断是否处于活跃状态
        abstract boolean shouldBeActive();
    
        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }
    
        void detachObserver() {
        }
    
        void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }
            mActive = newActive;
            changeActiveCounter(mActive ? 1 : -1);
            if (mActive) {
                //处于活跃状态,发送最新的值
                dispatchingValue(this);
            }
        }
    }
    

    2.3 observeForever 无条件感知数据变化

    在调用LiveData的observeForever方法时,没有传入被观察者,值传入了观察者,这就决定了调用observeForever之后无法根据Activity/Fragment的生命周期去判断合适感知数据,只能无条件的接收所有数据。这里用AlwaysActiveObserver对观察者进行了包装。

    @MainThread
    public void observeForever(@NonNull Observer<? super T> observer) {
        //判断是否是主线程
        assertMainThread("observeForever");
        //创建一个AlwaysActiveObserver对象,对Observer进行包装
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
        //ObserverWrapper包装了AlwaysActiveObserver和Observer
        //把Observer和AlwaysActiveObserver存入map
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing instanceof LiveData.LifecycleBoundObserver) {
            throw new IllegalArgumentException("Cannot add the same observer"
                                               + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        //这里传入的mActive一直是true,所以消息一直能无条件回调给观察者
        wrapper.activeStateChanged(true);
    }
    

    再看AlwaysActiveObserver,shouldBeActive固定返回true。所以在considerNotify方法中,一直能执行到observer.mObserver.onChanged((T) mData),把数据回调给观察者。

    private class AlwaysActiveObserver extends ObserverWrapper {
    
        AlwaysActiveObserver(Observer<? super T> observer) {
            super(observer);
        }
    
        @Override
        boolean shouldBeActive() {
            return true;
        }
    }
    

    3 流程图

    根据上边的源码分析,画出以下流程图。


    关注木水小站 (zhangmushui.cn)和公众号【木水Code】,及时获取更多技术干货。

    相关文章

      网友评论

        本文标题:Jetpack系列-LiveData使用和源码分析

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