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使用介绍
  • Android Jetpack组件App Startup简析
  • Android Jetpack组件之Hilt使用

本系列文章是各处copy过来的,个人感觉所有的开发者都应该尽早的熟悉Jetpack组件,相信一定会被它的魅力所吸引,最近也在完成一个使用以上所有组件实现的项目,作为对Jetpack组件的项目实践,下面来分析一下每个组件对项目开发的帮助。

2、LiveData简介

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

3、LiveData的使用

  • 创建一个LiveData实例来保存某种类型的数据
class TestViewModel : ViewModel() {var mCurrent: MutableLiveData<String>? = nullget() {if (field == null) {field = MutableLiveData()}return field}
}

请确保存储LiveData对象是在ViewModel中而不是activity或fragment里。

  • 创建一个定义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;@MainThreadpublic static LocationLiveData get(Context context) {if (sInstance == null) {sInstance = new LocationLiveData(context.getApplicationContext());}return sInstance;}private SimpleLocationListener listener = new SimpleLocationListener() {@Overridepublic void onLocationChanged(Location location) {setValue(location);}};private LocationLiveData(Context context) {locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);}@Overrideprotected void onActive() {locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);}@Overrideprotected void onInactive() {locationManager.removeUpdates(listener);}
}
  • onActive() :当LiveData对象具有Activity观察者时调用该方法
  • onInactive() :当LiveData对象没有任何Activity观察者时调用该方法
  • setValue(T) :方法更新LiveData实例的值,并通知任何Activity的观察者有关更改的信息

上面代码使用单例提供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> {@Overridepublic void postValue(T value) {super.postValue(value);}@Overridepublic 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)
@MainThreadpublic void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {if (owner.getLifecycle().getCurrentState() == DESTROYED) {// ignorereturn;}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的构造函数传递OwnermOwner = owner;}@Overrideboolean shouldBeActive() {return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);}// 实现GenericLifecycleObserver 当生命周期改变时回调onStateChanged@Overridepublic void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {removeObserver(mObserver); // DESTROYED时移除观察者return;}activeStateChanged(shouldBeActive());}@Overridevoid 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)
@MainThreadprotected 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() {@Overridepublic void run() {Object newValue;synchronized (mDataLock) {newValue = mPendingData;mPendingData = NOT_SET;}//noinspection uncheckedsetValue((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和观察者@Overridepublic void onChanged(@Nullable X x) {result.setValue(func.apply(x)); //在观察者回调中重新设着result的值,触发result的响应}});return result;
}

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

  • 首先创建MediatorLiveData实例,然后调用addSource()方法添加原数据对象source,新创建的观察者Observer,
  • 在观察者的onChange()方法中调用setValue()重新设置MediatorLiveData的result的值,此处设置的值是经过转换方法处理后的数据,在setValue()后就触发了转换后数据的更新

在将原数据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);}@Overridepublic 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的逻辑相似,只不过是多了一层数据的设置
@MainThreadpublic 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;@Overridepublic 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>() {@Overridepublic 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);}@Overrideboolean shouldBeActive() {return true;}
}

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

Android Jetpack组件之 LiveData使用-源码相关推荐

  1. Android Jetpack组件之Navigation使用-源码

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

  2. Android Jetpack组件之 Room使用-源码

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

  3. Android Jetpack组件之 Paging使用-源码

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

  4. Android Jetpack 组件之 Lifecycle源码

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

  5. Android Jetpack组件之Hilt使用

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

  6. Android Jetpack组件App Startup简析

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

  7. Android Jetpack组件之WorkManger使用介绍

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

  8. Android Jetpack组件之ViewModel使用

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

  9. Android Jetpack 组件之 Lifecycle使用

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

最新文章

  1. UIPickerView和UIDataPicker
  2. 深刻理解Vue中的组件
  3. ABAP程序打印Spool Request到PDF
  4. 塞班自带浏览器下载路径问题
  5. mysql中常见的几种索引
  6. linux脚本调用job,linux shell - 脚本中调用fg调取后台任务报错
  7. es5.4.0-CentOS-6.5-x86_64安装文档
  8. 拓端tecdat|r语言中使用Bioconductor 分析芯片数据
  9. Kafka 面试题(2022)
  10. 阿里、腾讯、华为人力资源体系
  11. bismark判断甲基化的比对原理
  12. 毕业实习感想—软件测试
  13. 网易暴力裁员事件,真的让人寒心
  14. 2022年最值得去的100家互联网大厂排名出来了
  15. 金融基础知识笔记(一)
  16. 详解开关电源RCD钳位电路工作过程
  17. 浅谈:6sigma与Minitab_北京八方在线Minitab代理商
  18. 标准正态分布alpha分位点
  19. python读取二进制文件 \xff\xfe \xef\xbb\xbf
  20. 你真的了解AsyncTask吗?AsyncTask源码分析

热门文章

  1. nginx php 错误日志,PHP 错误与异常的日志记录
  2. java一个点围着另一个点转_Java:按指定的度数值旋转另一个
  3. 解锁新姿势 |如何利用配置中心规范构建PaaS服务配置
  4. 递归算法转换为非递归算法的技巧
  5. SCWS 添加自定义词典
  6. 【NOIP2010】引水入城
  7. Android镜像文件的拆解
  8. HotSpotOverview.pdf
  9. [转载] New Concept English 1——Lesson 14 What colour's your…?
  10. 记一下常用shell,防止自己忘了。。。记性不好