我是靠谱客的博主 瘦瘦时光,最近开发中收集的这篇文章主要介绍Android Jetpack架构组件之 LiveData(使用、源码篇),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1、前言

最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面。

Android Architecture组件是Android Jetpack的一部分,它们是一组库,旨在帮助开发者设计健壮、可测试和可维护的应用程序,包含一下组件:

  •  带你领略Android Jetpack组件的魅力
  • Android Jetpack 架构组件之 Lifecycle(使用篇)
  • Android Jetpack 架构组件之 Lifecycle(源码篇)
  • Android Jetpack 架构组件之 ViewModel (源码篇)
  • Android Jetpack 架构组件之 LiveData(使用、源码篇)
  • Android Jetpack架构组件之 Paging(使用、源码篇)
  • Android Jetpack 架构组件之 Room(使用、源码篇)
  • Android Jetpack 架构组件之Navigation
  • Android Jetpack架构组件之WorkManger
  • 实战:从0搭建Jetpack版的WanAndroid客户端

上述时Android Architecture所提供的架构组件,本文主要从使用和源码的角度了解一下LiveData组件

2、LiveData简介

  • LiveData是一个具有生命周期感知特性的可观察的数据保持类,使用LiveData保存数据时,在每次订阅或数据更新时会自动回调设置的观察者从而更新数据,真正的实现了数据驱动的效果
  • LiveData的创建基本会在ViewModel中,从而使数据在界面销毁时继续保持
  • LiveData 认为观察者的生命周期处于STARTED状态或RESUMED状态下,表示观察者处于活动状态,LiveData只通知活跃的观察者更新数据
  • 注册一个实现该LifecycleOwner 接口的对象配对的观察者,当相应Lifecycle对象的状态改变为DESTROYED时移除观察者

3、LiveData的使用

  • 创建一个LiveData实例来保存某种类型的数据
class TestViewModel : ViewModel() {
    var mCurrent: MutableLiveData<String>? = null
        get() {
            if (field == null) {
                field = MutableLiveData()
            }
            return field
        }
}
  1. 请确保存储LiveData对象是在ViewModel中而不是活动或片段
  • 创建一个定义onChanged()方法的Observer对象,在数据变化时回调
//创建观察者对象
val nameObservable = Observer<String> {   // 创建观察者对象
    textView.text = it       // 定义onChange()方法中的操作
}
  • 使用LifecycleOwner的observe() 方法将观察者对象附加到LiveData对象,这将观察对象向LiveData对象订阅,以便通知其更改
// 如果在View Model中使用,先创建ViewModel的对象
mModel = ViewModelProviders.of(this).get(TestViewModel::class.java)

// mCurrent 订阅观察
mModel.mCurrent!!.observe(this, nameObservable)  
  1. 第一个参数传递的this就是LifecycleOwner 的实例,LiveData会根据Owner的声明周期自动作相应的处理
  2. observe()将nameObservable作参数调用后,如果LiveData数据有值,onChange()立即调用获取最新值
  3. 可以使用observeForever(Observer)方法注册一个没有关联的生命周期所有者对象的观察者,在这种情况下,观察者被认为总是活动的,因此总是通知修改,可以删除这些观察员调用removeObserver(Observer) 方法
  • LiveData允许UI控制器观察员订阅更新
// 设置两个点击事件,修改LiveData中的数据
btnChange.setOnClickListener { mModel.mCurrent!!.value = "AAAAA" }
btnB.setOnClickListener { mModel.mCurrent!!.value = "BBBBB" }
  1. 当LiveData对象保存的数据发生变化时,UI会自动响应更新
  2. 观察者在从非活动状态变为活动状态时也会收到更新
  • 运行结果:点击按钮后改变LiveData的数据,界面的TextView也随之改变

4、转换LiveData

  • Transformations.map():对存储在LiveData对象中的值应用函数,并将结果传播到下游
// 将返回开始示例中的 mCurrent 值的长度
var liveDataMap: LiveData<Int> = Transformations.map<String, Int>(mCurrent) { input: String -> input.length }
  • Transformations.switchMap() :第二个参数返回 一个LiveData
var livaDataSwich : LiveData<String> = Transformations.switchMap<String,String>(mCurrent){
    input: String? ->  MutableLiveData<String>().also { it.value = input!!.toLowerCase() }
}
  • 对上面转换的LiveData订阅观察
val lowObservable = Observer<String> {
    textViewLow.text = it
}
val lengthObservable = Observer<Int> {
    textViewLength.text = it.toString()
}

mModel.liveDataMap.observe(this, lengthObservable)
mModel.livaDataSwich.observe(this, lowObservable)

 

  • 使用场景
  1. 将LiveData对象分发给观察者之前对其中存储的值进行更改
  2. 需要LiveData根据另一个实例的值返回其他 实例
  3. 当基础的LiveData改变时,转换后的LiveData也会改变并且触发UI更新

5、扩展LiveData

public class LocationLiveData extends LiveData<Location> {
    private static LocationLiveData sInstance;
    private LocationManager locationManager;

    @MainThread
    public static LocationLiveData get(Context context) {
        if (sInstance == null) {
            sInstance = new LocationLiveData(context.getApplicationContext());
        }
        return sInstance;
    }

    private SimpleLocationListener listener = new SimpleLocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            setValue(location);
        }
    };

    private LocationLiveData(Context context) {
        locationManager = (LocationManager) context.getSystemService(
                Context.LOCATION_SERVICE);
    }

    @Override
    protected void onActive() {
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
    }

    @Override
    protected void onInactive() {
        locationManager.removeUpdates(listener);
    }
}
  1. onActive() :当LiveData对象具有活动观察者时调用该方法
  2. onInactive() :当LiveData对象没有任何活动观察者时调用该方法
  3. setValue(T) :方法更新LiveData实例的值,并通知任何活动的观察者有关更改的信息

上面代码使用单例提供LocationLiveData可以在Activity和Fragment之间实现共享,在onActive和onInactive中完成监听的注册和取消,当位置改变时回调Listener并调用setValue()设置LiveData的值,从而自动更新观察者中的数据,其实前面使用的MutableLiveData也是同样的一个扩展

  • 使用扩展LIveData

扩展的LiveData使用和正常使用一样,observe()方法将Fragmrnt(它是一个实例LifecycleOwner)作为第一个参数传递,使观察者绑定到Fragment的生命周期,如果Lifecycle对象未处于活动状态,则即使值发生更改,也不会调用观察者,在之后Lifecycle的对象被Destroy后,观察者被自动删除

6、源码分析

  • MutableLiveData
public class MutableLiveData<T> extends LiveData<T> {
    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}

从代码中可以看出MutableLiveData知识LiveData的一个扩展类,重写了LiveData中的抽象方法,postValue()和setValue()中也只是调用了super.postValue()和super.setValue(),也就是说所有的方法都是在LiveData中实现,

  • LiveData.observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer)
@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
        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,相信看过Lifecycler源码的(Android Jetpack框架之 Lifecycle(源码篇))应该会想到这里的作用是处理生命周期改变,在observe方法中执行了以下逻辑:

  1. 在observe中首先判断了当前Lifecycler的状态,当Destroy时即观察者不处于活跃状态,不用接收数据
  2. 创建LifecycleBoundObserver实例保存传入的LifecycleOwner和Observer,并保存在mObservers
  3. 添加LifecycleOwner的观察者,响应生命周期的变化
  • ObserverWrapper  &  LifecycleBoundObserver
private abstract class ObserverWrapper {
        final Observer<T> mObserver;
       
        ObserverWrapper(Observer<T> observer) {
            mObserver = observer;  // 保存观察者Observer
        }
        
        void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }

            mActive = newActive;
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            if (wasInactive && mActive) {
                onActive();  // 当Owner为活跃状态时回调onActive()
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive(); // 当Owner未活跃状态时回调onInactive()
            }
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }


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

        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) {
            super(observer); // 调用父类ObserverWrapper的构造函数传递Owner
            mOwner = owner;
        }

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

        // 实现GenericLifecycleObserver 当生命周期改变时回调onStateChanged
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver); // DESTROYED时移除观察者
                return;
            }
            activeStateChanged(shouldBeActive());
        }


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

上述执行的逻辑见代码中的注释,ObserverWrapper 在Owner活跃状态改变时回调onActive和onInactive方法,LifecycleBoundObserver主要利用Lifecycler的生命周期观察者GenericLifecycleObserver,前面设置了owner.getLifecycle().addObserver(wrapper)后,当生命周期改变时会回调onStateChange()方法,在生命周期为Destroy时移除Observer,在每次的生命周期变化时都会回调onStateChange(),然后调用shouldBeActive()判断当前活动是否出入活跃状态,shouldBeActive会根据Lifecycle中定义生命周期的顺序检测,只有当大于STARTED生命周期才为活跃,在activeStateChanged()也只会在活跃状态分发数据,然后调用dispatchingValue()分发数据;

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

 private void dispatchingValue(@Nullable ObserverWrapper initiator) {

            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
    }

setValue()中调用了dispatchingValue(),在dispatchingValue中遍历mObservers中所有的Observer,调用considerNotify()更新数据,由前面知道所有的LifecycleBoundObserver对象都保存在mObservers集合中

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

considerNotify()中调用mObserver的onChange()方法,这里的mObserver就是前面observe()中第二个参数的Observer,从而更新数据,简单就是说当LiveData中的数据改变时会遍历此LiveData所有的观察者,并回调onChange(),所以所有注册观察此数据的地方都会改变

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


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

postValue()其实是在非主线程中更新数据,其实他传递的Runnable中也是调用了setValue()方法,其余的操作只是通过ArchTaskExecutor和DefaultTaskExecutor将操作切换到主线程。

  • map()转换的源码分析
public static <X, Y> LiveData<Y> map(@NonNull LiveData<X> source,
        @NonNull final Function<X, Y> func) {
    final MediatorLiveData<Y> result = new MediatorLiveData<>(); //创建MediatorLiveData实例
    result.addSource(source, new Observer<X>() {  //调用MediatorLiveData.addSource传入LiveData和观察者
        @Override
        public void onChanged(@Nullable X x) {
            result.setValue(func.apply(x)); //在观察者回调中重新设着result的值,触发result的响应
        }
    });
    return result;
}

在调用Transformations.map()方法后,系统会先创建一个MediatorLiveData对象,MediatorLiveData也是LiveData的实例,从上面的代码大致可以看出map()的工作原理,

  1. 首先创建MediatorLiveData实例,然后调用addSource()方法添加原数据对象source,新创建的观察者Observer,
  2. 在观察者的onChange()方法中调用setValue()重新设置MediatorLiveData的result的值,此处设置的值是经过转换方法处理后的数据,在setValue()后就触发了转换后数据的更新
//MediatorLiveData.addSource()
@MainThread
public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<S> onChanged) {
    Source<S> e = new Source<>(source, onChanged); //  封装原数据LiveData和观察者Observer
    Source<?> existing = mSources.putIfAbsent(source, e);
    if (hasActiveObservers()) {
        e.plug(); //调用Source.plug()添加观察者
    }
}

在将原数据LiveData和传入的Observer封装在Source中,然后缓存在mSources中,然后调用Source.plug()为Source添加观察者

private static class Source<V> implements Observer<V> {
    final LiveData<V> mLiveData; 
    final Observer<V> mObserver;
    int mVersion = START_VERSION;
    Source(LiveData<V> liveData, final Observer<V> observer) {
        mLiveData = liveData;
        mObserver = observer;
    }
    void plug() { // 添加永久观察者
        mLiveData.observeForever(this);
    }
    void unplug() { //移除永久观察者
        mLiveData.removeObserver(this);
    }
    @Override
    public void onChanged(@Nullable V v) {
        if (mVersion != mLiveData.getVersion()) {
            mVersion = mLiveData.getVersion();
            mObserver.onChanged(v); // 在永久观察的回调方法中回调Observer.onChange()
        }
    }
}

在Source类中保存这传入的LivaData和Observer,然后调用plugin()方法为LiveData添加本地观察者,在原数据mLivaData发生改变时回调onChange,在onChange()中回调保存的Observer中的方法,此处执行的是在map()中匿名创建的Observer,由上面知道在Observer中调用了修改数据的方法并重新设置数据,从而更新掉map转换的数据

 - switchMap():源码和map的逻辑相似,只不过是多了一层数据的设置

@MainThread
    public static <X, Y> LiveData<Y> switchMap(@NonNull LiveData<X> trigger,
            @NonNull final Function<X, LiveData<Y>> func) {
        final MediatorLiveData<Y> result = new MediatorLiveData<>();
        result.addSource(trigger, new Observer<X>() {
            LiveData<Y> mSource;

            @Override
            public void onChanged(@Nullable X x) {
                LiveData<Y> newLiveData = func.apply(x);
                if (mSource == newLiveData) {
                    return;
                }
                if (mSource != null) {
                    result.removeSource(mSource);
                }
                mSource = newLiveData;
                if (mSource != null) {
                    result.addSource(mSource, new Observer<Y>() {
                        @Override
                        public void onChanged(@Nullable Y y) {
                            result.setValue(y);
                        }
                    });
                }
            }
        });
        return result;
    }
  • observeForever()源码分析

从名字上即可看出它的作用,普通的监听方法只会在活动处于活跃状态,即处于Started和Destory之间才会分发数据,而observeForever会在任何时候都会分发数据,它的实现逻辑很简单只是重写了上面的shouldBeActive()方法,使之总是返回true

private class AlwaysActiveObserver extends ObserverWrapper {

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

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

LiveData的使用和源码分析到此结束了,LiveData整个过程就是两部分,一是使用LifeCycleOwner感知声明周期的变化,两一个就是储存并遍历Observer,在数据改变时回调所有的观察者,LiveData的实现还是比较简单的,希望本篇文章的分析对大家有所帮助。

最后

以上就是瘦瘦时光为你收集整理的Android Jetpack架构组件之 LiveData(使用、源码篇)的全部内容,希望文章能够帮你解决Android Jetpack架构组件之 LiveData(使用、源码篇)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部