【Jetpack】了解LiveData

Quibbler 2020-12-20 617

了解LiveData


        前段时间学习ViewModel的时候就提到LiveData,单独的ViewModel并不能发挥它的全部“实力”。所以需要继续学习LiveData,善于实践结合ViewModel完成MV的解耦。



1、LiveData简介

        LiveData组件是什么?有哪些优势?这些在Google的官网都能找到答案。详见LiveData Overview

        

1.1、介绍

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

        LiveData抽象类有几个实现子类,分别是:MutableLiveDataMediatorLiveData等。

        MutableLiveData继承自LiveData,暴露了修改value的方法,因为LiveData中的修改值方法权限是protected。

        MediatorLiveData又继承自MutableLiveData类,合并多个LiveData源,在任何原始LiveData源对象改变后,MediatorLiveData对象的Observer会被触发。

          并且可以借助Transformations转换或修改LiveData返回的数据,详见Transform LiveData


1.2、优势

        使用LiveData有以下优势,这些优势解决的正是让Android开发者头疼的地方:

        不会发生内存泄漏

        不会因 Activity 停止而导致崩溃

        不再需要手动处理生命周期

        数据始终保持最新状态

        共享资源


1.3、引入依赖

        在build.gradle中加上使用LiveData组件所需的相关依赖,更多Lifecycle组件详见Jetpack > Libraries > Lifecycle

dependencies {
    ...
    def lifecycle_version = "2.2.0"
    // ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
    // LiveData
    implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
    ...
}



2、LiveData简单用法

        LiveData使用起来也很方便,主要一下三步。一般LiveData放在ViewModel中使用。

        创建保存特定数据类型的LiveData实例;

        创建Observer对象,作为参数传入LiveData.observe()方法添加观察者;

        更新Livedata对象存储的数据;


2.1、创建LiveData

        在ViewModel中创建LiveData<T>对象持有数据,用到的时候再初始化。关于ViewModel的用法详见ViewModel视图与数据的桥梁

    public class UserModel extends ViewModel {
        private MutableLiveData<String> userName;
        
        public MutableLiveData<String> getUserName() {
            if (null == userName) {
                userName = new MutableLiveData<>();
            }
            return userName;
        }
        
    }


2.2、添加观察者

        在UI层通过ViewModel实例获取其中持有的LiveData数据对象:

    UserModel userModel = new ViewModelProvider(this).get(UserModel.class);
    MutableLiveData<String> name = userModel.getUserName();


2.3、添加观察者

        LiveData其实就是观察者模式。它的关键就是这步,在UI层给LiveData对象添加观察者,当数据变化时会通过onChanged(T t)回调方法通知观察者,参数t就是变化的值。有两种添加模式

        observe(LifecycleOwner owner,Observer<? super T> observer)

    name.observe(this, new Observer<String>() {
        @Override
        public void onChanged(String s) {
            Log.d(TAG, "observe " + s);
        }
    });

        observeForever(Observer<? super T> observer)

    name.observeForever(new Observer<String>() {
        @Override
        public void onChanged(String s) {
            Log.d(TAG, "observeForever " + s);
        }
    });

        使用该方法,一定要注意在不需要的时候需要手动调用removeObserver(final Observer<? super T> observer)方法移除观察者。

  

2.4、更新数据

        获取数据可以调用LiveData中的getValue()方法。只有MutableLiveData类型的对象才可以更新其中的数据,有两种方法:

        setValue(T value):必须在主线程调用该方法

    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }

        postValue(T value):可以在子线程中调用,内部通过Handler在主线程中更新数据。

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


2.5、活跃态、非活跃态

        我们还可以自定义LiveData,重写onActive()onInactive()方法,当LiveData被添加观察者时进行初始化或注册操作,当LiveData没有观察者被暂时不被观察的时候就可以移除资源。

    public class MyLiveData extends LiveData {
        @Override
        protected void onActive() {
            super.onActive();
            //当活动观察者的数量从0更改为1时调用。
        }
        
        @Override
        protected void onInactive() {
            super.onInactive();
            //当活动观察者的数量从1更改为0时调用。
        }
    }



3、源码分析

        先会用,再看其中的实现原理。LiveData主要涉及到三个技术要点:注册观察者、观察者的回调流程、生命周期相关处理。关于ViewModel的源码另见ViewModel视图与数据的桥梁


3.1、添加观察者

        通过前面的简单使用,了解到给LiveData添加观察者使用的是observe()observeForever()方法。来看看observe()方法,第一个参数LifecycleOwner一般就是实现了LifecycleOwner接口的Activity或者Fragment。

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

        内部将传入的LifecycleOner和Observer实例用LiveData中的内部类LifecycleBoundObserver包装起来。LifecycleBoundObserver包装了观察者和被观察者,并且实现了LifecycleEventObserver(LifecycleObserver)接口(涉及到Lifecycle,详见Lifecycle生命周期感知组件)。

    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() {
            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;
            }
            activeStateChanged(shouldBeActive());
        }
        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }
        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }

        回到observe()方法中,有一步判断,不能将同一个观察者设置给不同的Lifecycle实例。也就是传入的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;
        }

        最后一步,将包装好的观察者添加给LifecycleOwner监听生命周期的变化。

        ...
        owner.getLifecycle().addObserver(wrapper);
    }


3.2、更新通知

        当我们更新LiveData中的数据的时候,是如何回调给注册的观察者呢?来看看更新value的方法setValue(T value)

    @MainThread
    protected void setValue(T value) {
        //必须在主线程调用setValue(T value)方法
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }

        setValue(T value)操作涉及到几个全局变量:

    private volatile Object mData;
    // 当setData被调用时,设置挂起的数据,实际的数据交换发生在主线程上
    @SuppressWarnings("WeakerAccess") /* synthetic access */
    volatile Object mPendingData = NOT_SET;
    private int mVersion;


        接着调用了dispatchingValue()方法,注意这里传的参数是null。这一系列的操作都在主线程,否则子线程操作容易涉及到多线程同步的问题,复杂化!

    @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 {
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

        dispatchingValue()方法传入的参数类型就是之前包装了观察者和被观察者的包装类ObserverWrapper。如果不为null,就只更新这个观察者。如果为null,就遍历通知在mObservers中注册的所有观察者。通过considerNotify(ObserverWrapper observer)方法

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

      最后一行代码,就可以看到调用了Observer的onChange(T t)方法,回调通知观察者,通样是在UI主线程,不能做耗时操作。另一个更新值的方法postValue(T value)类似,之所以可以在子线程调用,是因为内部封装了更新值的任务,通过主线程的MainHandler执行。

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


3.3、生命周期

        当Activity、Fragment生命周期发生变化的时候,LiveData是如何感知的呢?答案就在刚刚提到的LifecycleBoundObserver包装类中:

    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() {
            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;
            }
            activeStateChanged(shouldBeActive());
        }
        
        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }
        
        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }

        之前学习Lifecycle的时候知道Activity的生命周期发生变化的时候会回调给LifecycleEventObserver,回调其中的onStateChanged(LifecycleOwner source,Lifecycle.Event event)方法,该方法在LifecycleBoundObserver中的实现如下:

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

        当Activity生命周期DESTORYED时,会移除观察者,调用的是LiveData的方法removeObserver(Observer<? super T> observer)

    public void removeObserver(@NonNull final Observer<? super T> observer) {
        assertMainThread("removeObserver");
        ObserverWrapper removed = mObservers.remove(observer);
        if (removed == null) {
            return;
        }
        removed.detachObserver();
        removed.activeStateChanged(false);
    }

        detachObserver()将会从LifecycleOwner中移除该包装类观察者对象自身:

        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }

        并且调用activeStateChanged(boolean newActive)设置不再激活,该方法是ObserverWrapper包装类中的方法。

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

        在这里可以看到onActive()和onInactive()空方法回调,当首次给LiveData注册观察者,以及移除全部观察者时分别回调。

        最后,从LifecycleBoundObserver中的shouldBeActive()方法,我们可以看到LiveData只有当Activity或Fragment的Lifecycle状态处于STARTEDRESUME才会激活状态。

        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        但是对于通过observeForever(Observer<? super T> observer)方法注册的则不同,使用的是AlwaysActiveObserver类包装,其中该方法始终返回true,也就是不管Activity生命周期处于什么状态,都会回调通知前台更新数据,除非手动移除观察者!

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



参考资料:

        Android Developers > Guides > LiveData Overview

        Jetpack > Libraries > Lifecycle

        带你深入了解官方架构组件LiveData

        Android应用结构之LiveData

        LiveData的工作原理

        LiveData

        LiveData的用法


不忘初心的阿甘
最新回复 (0)
    • 安卓笔记本
      2
        登录 注册 QQ
返回
仅供学习交流,切勿用于商业用途。如有错误欢迎指出:fluent0418@gmail.com