Jetpack 架构组件:LiveData

简介

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

优势

  • UI和实时数据保持一致

LiveData 遵循观察者模式。当数据更新后,LiveData就会通知它的所有观察者;与RxJava的方法不同的是,LiveData并不是通知所有观察者,它只会通知处于活跃状态(Activity/Fragment 处于STARTED和RESUMED 状态)的观察者。

  • 不会发生内存泄漏

观察者被绑定到组件的生命周期上,当被绑定的组件销毁(destory)时,观察者会立刻自动清理自身的数据。

  • 不需要手动解除观察

开发者不需要在onPause或onDestroy方法中解除对LiveData的观察,因为LiveData能感知生命周期状态变化,所以会自动管理所有这些操作。

  • 解决Configuration Change问题

在屏幕发生旋转或者被回收再次启动,立刻就能收到最新的数据。

用法

LiveData 和ViewModel 搭配使用

  • 创建LiveData实例,指定源数据类型

LiveData是一个数据的包装。具体的包装对象可以是任何数据,包括集合。LiveData是一个抽象类,它的最简单的实现类为MutableLiveData。

public class ExViewModel extends ViewModel {

    private MutableLiveData<Integer>  num;

    public MutableLiveData<Integer> getNum() {
        if (num == null) {
            num = new MutableLiveData<>();
        }
        return num;
    }
}
  • 观察LiveData中的数据

创建Observer实例,实现onChanged()方法,用于接收源数据变化并刷新UI。

num.observe(this, new Observer<Integer>() {
            @Override
            public void onChanged(Integer integer) {
                tv_num.setText(String.valueOf(integer));
            }
 });

通过LiveData.observe()方法对LivaData所包装的数据进行观察。在onChanged方法就会收到我们修改之后的数据,我们就可以对UI进行更改了。

  • 使用LiveData 更新数据
// 获取ViewModel 对象
ExViewModel model = new ViewModelProvider(this).get(ExViewModel.class);
// 获取LiveData 对象
MutableLiveData<Integer> num = model.getNum();
        
btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                i++;
                num.setValue(i);
            }
        });

通过LiveData.postValue/LiveData.setValue()方法修改数据。注意:setValue()方法必须在主线程使用,如果是在工作线程中更新LiveData,则可以使用postValue()方法。

效果:
在这里插入图片描述

转换LiveData 数据

如果想要在LiveData对象分发给观察者之前对其中存储的值进行更改,可以使用Transformations.map()和Transformations.switchMap()。

  • Transformations.map
MutableLiveData<Integer> num=new MutableLiveData<>();
  
  LiveData<String>  info=Transformations.map(num, new Function<Integer, String>() {
            @Override
            public String apply(Integer input) {

                return input+"次点击";
            }
        });
        
    info.observe(this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                Log.e(TAG,"--->"+s);
            }
        }); 
    
    num.setValue(1);
    
// 执行结果:
ExJetPackActivity: --->1次点击

通过Transformations.map()方法对源数据Integer 类型LiveData,修改成String 类型LiveData。

  • Transformations.switchMap
    如果想要根据某个值 切换观察不同LiveData数据,则可以使用Transformations.switchMap()方法。
MutableLiveData<String> work=new MutableLiveData<>();
        work.setValue("加班");
        
        MutableLiveData<String> rest=new MutableLiveData<>();
        rest.setValue("双休");

        MutableLiveData<Boolean> conditions=new MutableLiveData<>();
        conditions.setValue(true);

        LiveData<String> result=Transformations.switchMap(conditions, new Function<Boolean, LiveData<String>>() {
            @Override
            public LiveData<String> apply(Boolean condition) {
                if (condition){
                    return rest;
                }
                return work;
            }
        });

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

// 执行结果:
ExJetPackActivity: --->双休

work、rest 作为数据源,conditions 作为判断的条件,如果为true,返回rest;否则,返回work。

  • 合并多个LiveData数据源
    MediatorLiveData是LiveData 的子类,允许合并多个LiveData数据源。
 MediatorLiveData<String> mediatorLiveData = new MediatorLiveData<>();

        MutableLiveData<String> source1 = new MutableLiveData<>();
        MutableLiveData<String> source2 = new MutableLiveData<>();

        mediatorLiveData.addSource(source1, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                Log.e(TAG,"-source1-->"+s);
                mediatorLiveData.setValue(s);
            }
        });

        mediatorLiveData.addSource(source2, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                Log.e(TAG,"--source2->"+s);
                mediatorLiveData.setValue(s);
            }
        });

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

        source1.setValue("上班");
        source2.setValue("休息");

执行结果:
ExJetPackActivity: -source1-->上班
ExJetPackActivity: --mediator->上班

ExJetPackActivity: --source2->休息
ExJetPackActivity: --mediator->休息

通过MediatorLiveData的addSource将两个MutableLiveData合并到一起,这样当任何一个MutableLiveData数据发生变化时,MediatorLiveData都可以感知到。

源码分析

添加观察者

通过调用LiveData的observe方法来注册观察者,接着查看LiveData的observe方法。

 private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
            new SafeIterableMap<>();
    ...
    
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        //如果被观察者的当前的状态是DESTROYED,就return
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        //使用LifecycleOwner、observer 组装成LifecycleBoundObserver,添加到mObservers中
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        // 注释1
        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) {
          //说明已经添加到mObservers中
            return;
        }
        //注释2
        owner.getLifecycle().addObserver(wrapper);
    }

注释1处将observer和LifecycleBoundObserver存储到SafeIterableMap<Observer<? super T>, ObserverWrapper>mObservers中,putIfAbsent方法,如果传入key对应的value已经存在,就返回存在的value,不进行替换。如果不存在,就添加key和value,返回null。

如果等于null,在注释2处会将LifecycleBoundObserver添加到Lifecycle中完成注册,这样当我们调用LiveData的observe方法时,实际上是LiveData内部完成了Lifecycle的观察者的添加,这样LiveData自然也就有了观察组件生命周期变化的能力。

事件回调

LiveData添加了观察者LifecycleBoundObserver,接着看如何进行回调的:

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

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

        @Override
        boolean shouldBeActive() {
            // 至少是STARTED状态
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                //LifecycleOwner变成DESTROYED状态,则移除观察者
                removeObserver(mObserver);
                return;
            }
            activeStateChanged(shouldBeActive());
        }

        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }

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

LifecycleBoundObserver是LiveData的内部类,是对原始Observer的包装。它的构造方法参数是LifecycleOwner类型和Observer类型的参数,把LifecycleOwner和Observer绑定在一起。

LifecycleBoundObserver继承了ObserverWrapper类,重写了shouldBeActive方法,用于判断当前传入的组件的状态是否是Active的,Active状态包括STARTED和RESUMED状态。

LifecycleBoundObserver实现了GenericLifecycleObserver接口,当组件状态发生变化时,会调用onStateChanged方法;当组件处于DESTROYED状态时,会调用removeObserver方法,来移除observer。这就是LiveData自动移除观察者的原因。

如果不是DESTROYED状态,将调用父类ObserverWrapper的activeStateChanged()方法处理 这个生命周期状态变化,shouldBeActive()的值作为参数。

接着,看下抽象类ObserverWrapper

private abstract class ObserverWrapper {
        final Observer<? super T> mObserver;
        boolean mActive;
        int mLastVersion = START_VERSION;
        ...
        void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
            //活跃状态 未发生变化时,不会处理
                return;
            }
            
            mActive = newActive;
            //没有活跃的观察者
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            //mActive为true表示变为活跃
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            if (wasInactive && mActive) {
                onActive();//活跃的观察者数量 由0变为1
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();//活跃的观察者数量 由1变为0
            }
            if (mActive) {
                dispatchingValue(this);//观察者变为活跃,就进行数据分发
            }
        }
    }

mActive是ObserverWrapper的属性,表示此观察者是否活跃。如果活跃状态未发生变化时,不会处理。activeStateChanged方法会根据Active状态和处于Active状态的组件的数量,会对应调用onActive方法和onInactive方法回调,这两个方法用于拓展LiveData对象。

如果 mActive为true,即观察者处于Active状态,会调用dispatchingValue方法,并将自身传进去。

// LiveData 源码

void dispatchingValue(@Nullable ObserverWrapper initiator) {
        // 当前正在分发
        if (mDispatchingValue) {
           // 分发无效 
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;//标记正在分发
        do {
             //分发有效
            mDispatchInvalidated = false; 
            //observerWrapper不为空,使用considerNotify()通知真正的观察者
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
            //observerWrapper为空,遍历通知所有的观察者
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                        
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }
    
    private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {//1
            return;
        }
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);//2
            return;
        }
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        observer.mObserver.onChanged((T) mData);//3
    }

considerNotify方法中做了多次的判断,注释1处,如果ObserverWrapper的mActive值不为true,就直接return。

注释2处,如果当前observer对应组件的状态不是Active,就会再次调用activeStateChanged方法,并传入false,其方法内部会再次判断是否执行onActive方法和onInactive方法回调。

注释3处,如果判断条件都满足,会调用Observer的onChanged方法,这个方法正是使用LiveData的observe方法的回调,值是LivaData的变量mData。

小结: considerNotify()方法只有出于活跃状态且数据是最新的,才会去分发数据,最后回调到onChanged方法。

数据更新

当调用MutableLiveData的observe方法后,还需要通过postValue/setValue方法来更新数据,区别在于postValue(value)用于子线程。

// LiveData 源码

 static final Object NOT_SET = new Object();
 
 volatile Object mPendingData = NOT_SET;
 
 private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            // 最终会调用setValue()方法
            setValue((T) newValue);
        }
    };
    
    @MainThread
    protected void setValue(T value) {// 注释1
        assertMainThread("setValue");
        //mVersion++记录当前发送的消息的次数,用于和observer的version作对比,防止消息重复
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }
    
    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
          // 抛到主线程
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

从上面的代码来看,可以发现postValue()方法实际上就是将setValue方法切换到主线程调用。setValue()方法是运行在主线程中的,其内部调用了dispatchingValue方法的参数ObserverWrapper为null情况(即遍历所有观察者进行分发回调)。无论是LiveData的observe方法还是LiveData的postValue/setValue方法都会调用dispatchingValue方法。

Transformations map 方法分析

 // Transformations 类源码
   
    @MainThread
    public static <X, Y> LiveData<Y> map(
            @NonNull LiveData<X> source,
            @NonNull final Function<X, Y> mapFunction) {
        final MediatorLiveData<Y> result = new MediatorLiveData<>();
        result.addSource(source, new Observer<X>() {
            @Override
            public void onChanged(@Nullable X x) {
                result.setValue(mapFunction.apply(x));
            }
        });
        return result;
    }

Transformations.map方法运行在主线程,创建了MediatorLiveData,紧接着调用了它的addSource方法,传入参数是LiveData 类型的source 和 新建 Observer 类型的内部类。

// MediatorLiveData 类源码
    
    private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap<>();
    
    @MainThread
    public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {
        Source<S> e = new Source<>(source, onChanged);
        Source<?> existing = mSources.putIfAbsent(source, e);
        if (existing != null && existing.mObserver != onChanged) {
            throw new IllegalArgumentException(
                    "This source was already added with the different observer");
        }
        if (existing != null) {
            return;
        }
        if (hasActiveObservers()) {
            e.plug();
        }
    }

MediatorLiveData 类是LiveData的子类,它的addSource()方法将传进来的LiveData和onChanged封装到Source类中。如果MediatorLiveData有活跃观察者,就调用plug()方法。

// MediatorLiveData 类源码

   private static class Source<V> implements Observer<V> {
        final LiveData<V> mLiveData;
        final Observer<? super V> mObserver;
        int mVersion = START_VERSION;

        Source(LiveData<V> liveData, final Observer<? super V> observer) {
            mLiveData = liveData;
            mObserver = observer;
        }

        void plug() {// 注释1
            mLiveData.observeForever(this);
        }

        void unplug() {
            mLiveData.removeObserver(this);
        }

        @Override
        public void onChanged(@Nullable V v) {
            if (mVersion != mLiveData.getVersion()) {
                mVersion = mLiveData.getVersion();
                // 注释2
                mObserver.onChanged(v);
            }
        }
    }
    
// LiveData 类源码
    @MainThread
    public void observeForever(@NonNull Observer<? super T> observer) {
        assertMainThread("observeForever");
        // 注释3
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
        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;
        }
        wrapper.activeStateChanged(true);
    }

Source是MediatorLiveData的内部类,是对源LiveData的包装。注释1处Source的plug方法会调用LiveData的observeForever方法。

注释2处Transformations.map方法传入的Observer的回调方法onChanged()会在此调用。

注释3处用AlwaysActiveObserver来对Observer进行包装,紧接着调用AlwaysActiveObserver的activeStateChanged方法,其内部实际调用的是ObserverWrapper的activeStateChanged方法。

下面,接着看AlwaysActiveObserver 源码

// LiveData 类源码
 private class AlwaysActiveObserver extends ObserverWrapper {

        AlwaysActiveObserver(Observer<? super T> observer) {
            super(observer);
        }

        @Override
        boolean shouldBeActive() {
            return true;
        }
    }

AlwaysActiveObserver是LiveData的内部类,它继承自ObserverWrapper。从shouldBeActive()方法返回true,可以看出AlwaysActiveObserver和ObserverWrapper相比来说,它是永远处于Active状态的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值