| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> Jetpack架构组件 (四)-- LiveData使用与原理分析 -> 正文阅读 |
|
[移动开发]Jetpack架构组件 (四)-- LiveData使用与原理分析 |
前言在 LiveData 出现之前,一般状态分发我们使用EventBus或者RxJava,这些都很容易出现内存泄漏问题,而且需要我们手动管理生命周期。而 LiveData 则规避了这些问题,LiveData 是一个持有 Activity、Fragment 生命周期的数据容器。当数据源发生变化的时候,通知它的观察者更新 UI 界面。同时它可以只通知处于 Active 状态的观察者更新界面。所以不用担心内存泄漏问题。一般来说,LiveData很少单独使用,它更多的和Android Jetpack的其他组件搭配使用,比如和ViewModel。这篇文章就来介绍LiveData的使用。 1、 什么是LiveDataLiveData 是一个可观察的数据持有者,和常规的observable不同,LiveData 是可以感知生命周期的,也就是说它能够在 Activity、Fragment、Service 中正确的处理生命周期。 LiveData 的数据源一般是 ViewModel,也可以是其它可以更新 LiveData 的组件。当数据更新后,LiveData 就会通知它的所有观察者,比如 Activity。与 RxJava 的方法不同的是,LiveData 可以不通知所有观察者,它可以只通知处于 Active 状态的观察者。这对于Activity 和 Service 特别有用,因为它们可以安全地观察 LiveData 对象而不用担心内存泄漏的问题。还有一点需要注意的是一旦观察者重新恢复到活跃状态,它将会重新收到 LiveData 的最新数据。 2、 LiveData的基本使用LiveData 是一个抽象类,它的最简单的实现类为 MutableLiveData,使用方法如下所示: public class MainActivity extends AppCompatActivity { ? MutableLiveData<String> mutableLiveData = new MutableLiveData<>(); ? @Override ? protected void onCreate(Bundle savedInstanceState) { ? ? ? super.onCreate(savedInstanceState); ? ? ? setContentView(R.layout.activity_main); ? ? ? ? mutableLiveData.observe(this, new Observer<String>() { ? ? ? ? ? @Override ? ? ? ? ? public void onChanged(@Nullable final String s) { ? ? ? ? ? ? ? Log.d("MainActivity", "onChanged:"+s); ? ? ? ? ? } ? ? ? }); ? ? ? mutableLiveData.postValue("LiveData 基本使用"); ? ? } } MutableLiveData 的 observe 方法有两个参数分别是 LifecycleOwner 和 除了 MutableLiveData 的 postValue 方法,还可以使用 setValue 方法,它们之前的区别是,setValue 方法必须在主线程使用,如果是在子线程线程中更新 LiveData,则可以使用 postValue 方法。 3、 更改LiveData中的数据如果我们想要在 LiveData 对象分发给观察者之前对其中存储的值进行更改,可以使用 Transformations.map() 和Transformations.switchMap(),下面通过简单的例子来讲解它们。 2.1 Transformations.map()如果想要在 LiveData 对象分发给观察者之前对其中存储的值进行更改,可以使用Transformations.map()。 public class MainActivity extends AppCompatActivity { ? MutableLiveData<String> mutableLiveData = new MutableLiveData<>(); ? @Override ? protected void onCreate(Bundle savedInstanceState) { ? ? ? super.onCreate(savedInstanceState); ? ? ? setContentView(R.layout.activity_main); ? ? ? ? mutableLiveData.observe(this, new Observer<String>() { ? ? ? ? ? @Override ? ? ? ? ? public void onChanged(@Nullable final String s) { ? ? ? ? ? ? ? Log.d("MainActivity", "onChanged:"+s); ? ? ? ? ? } ? ? ? }); ? ? ? LiveData transformedLiveData = Transformations.map(mutableLiveData, new Function<String, Object>() { ? ? ? ? ? @Override ? ? ? ? ? public Object apply(String name) { ? ? ? ? ? ? ? return name + " + Transformations.map 的使用"; ? ? ? ? ? } ? ? ? }); ? ? ? transformedLiveData.observe(this, new Observer() { ? ? ? ? ? @Override ? ? ? ? ? public void onChanged(@Nullable Object o) { ? ? ? ? ? ? ? Log.d("MainActivity", "onChanged2:"+o.toString()); ? ? ? ? ? } ? ? ? }); ? ? ? mutableLiveData.postValue("LiveData 基本使用"); ? } } 通过Transformations.map(),在mutableLiveData的基础上又加上了字符串" + Transformations.map 的使用"。 运行结果如下所示: 2.2 Transformations.switchMap()public class MainActivity extends AppCompatActivity { ? private MutableLiveData<String> mutableLiveData1; ? private MutableLiveData<String> mutableLiveData2; ? private MutableLiveData<Boolean> liveDataSwitch; ? private LiveData transformedLiveData; ? @Override ? protected void onCreate(Bundle savedInstanceState) { ? ? ? super.onCreate(savedInstanceState); ? ? ? setContentView(R.layout.activity_main); ? ? ? mutableLiveData1 = new MutableLiveData<>(); ? ? ? mutableLiveData2 = new MutableLiveData<>(); ? ? ? liveDataSwitch = new MutableLiveData<>(); ? ? ? ? ? transformedLiveData= Transformations.switchMap(liveDataSwitch, new Function<Boolean, LiveData<String>>() { ? ? ? ? ? @Override ? ? ? ? ? public LiveData<String> apply(Boolean input) { ? ? ? ? ? ? ? if (input) { ? ? ? ? ? ? ? ? ? return mutableLiveData1; ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? return mutableLiveData2; ? ? ? ? ? ? ? } ? ? ? ? ? } ? ? ? }); ? ? ? ? transformedLiveData.observe(this, new Observer<String>() { ? ? ? ? ? @Override ? ? ? ? ? public void onChanged(@Nullable final String s) { ? ? ? ? ? ? ? Log.d("MainActivity", "onChanged:" + s); ? ? ? ? ? } ? ? ? }); ? ? ? liveDataSwitch.postValue(false); ? ? ? mutableLiveData1.postValue("Transformations.switchMap 用法1"); ? ? ? mutableLiveData2.postValue("Transformations.switchMap 用法2"); ? } }
2.3 合并多个LiveData数据源MediatorLiveData 继承自 mutableLiveData,它可以将多个 LiveData 数据源集合起来,可以达到一个组件监听多个 LiveData 数据变化的目的,用法如下所示: public class MainActivity extends AppCompatActivity { ? private MutableLiveData<String> mutableLiveData1; ? private MutableLiveData<String> mutableLiveData2; ? private MediatorLiveData mediatorLiveData; ? ? @Override ? protected void onCreate(Bundle savedInstanceState) { ? ? ? super.onCreate(savedInstanceState); ? ? ? setContentView(R.layout.activity_main); ? ? ? mutableLiveData1 = new MutableLiveData<>(); ? ? ? mutableLiveData2 = new MutableLiveData<>(); ? ? ? mediatorLiveData = new MediatorLiveData<String>(); ? ? ? ? mediatorLiveData.addSource(mutableLiveData1, new Observer() { ? ? ? ? ? @Override ? ? ? ? ? public void onChanged(@Nullable Object o) { ? ? ? ? ? ? ? Log.d("MainActivity", "onChanged1:" + o.toString()); ? ? ? ? ? } ? ? ? }); ? ? ? ? mediatorLiveData.addSource(mutableLiveData2, new Observer() { ? ? ? ? ? @Override ? ? ? ? ? public void onChanged(@Nullable Object o) { ? ? ? ? ? ? ? Log.d("MainActivity", "onChanged2:" + o.toString()); ? ? ? ? ? } ? ? ? }); ? ? ? mediatorLiveData.observe(this, new Observer() { ? ? ? ? ? @Override ? ? ? ? ? public void onChanged(@Nullable Object o) { ? ? ? ? ? ? ? Log.d("MainActivity", "onChanged:" + o.toString()); ? ? ? ? ? } ? ? ? }); ? ? ? mutableLiveData1.postValue("mutableLiveData 1"); ? ? ? mutableLiveData2.postValue("mutableLiveData 2"); ? ? ? mediatorLiveData.postValue("mediatorLiveData 使用"); ? } } 通过 MediatorLiveData 的 addSource 将两个 MutableLiveData 合并到一起,这样当任何一个 MutableLiveData数据发生变化时,MediatorLiveData 都可以感知到,运行结果如下所示: 4、LiveData源码解析由于 LiveData 是一个 abstract class,我们不能直接生成他的实例。官方有提供他的实现类 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); ? } } 创建了 LiveData 后,需要通过 observe 方法或者 observeForever 方法设置一个观察者,这个观察者接口就是Observer,代码如下: public interface Observer<T> { ? // 这个回调发生在主线程 ? void onChanged(T t); } LiveData 的添加观察者的代码如下: public abstract class LiveData<T> { ... // 只有onStart之后,onStop之前,对数据的修改才会触发 observer.onChanged() ? public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) { ? ? } ? ? ? ? // 无论何时,只要数据发生改变,就会触发 observer.onChanged() ? public void observeForever(@NonNull Observer<? super T> observer) { ? ? ? } ... } observeForever 的实现跟 observe 是类似的,这里我们重点看一下 observe()的实现过程,代码如下: // 只能在主线程调用 @MainThread public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) { ? assertMainThread("observe"); ? //如当前UI的状态的是DESTROYED,就不绑定这个回调了 ? if (owner.getLifecycle().getCurrentState() == DESTROYED) { ? ? ? // ignore ? ? ? return; ? } ? //创建生命周期感知的观察者包装类(把注册进来的observer包装成一个具有生命周边边界的观察者) ? LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer); ? //接着会判断该观察是否已经注册过了,如果是则抛异常, 对应观察者只能与一个owner绑定,不允许重复注册 ? 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; ? } ? //把wrapper与Activity/Fragment的生命周期,建立关系, ? //当UI的生命周期发生变化的时候,就会去回调wrapper中的onStateChanged方法 ? owner.getLifecycle().addObserver(wrapper); } 4.2 LifecycleBoundObserverclass LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver { ? @NonNull ? final LifecycleOwner mOwner; ? ? LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) { ? ? ? super(observer); ? ? ? mOwner = owner; ? } ? ? @Override ? boolean shouldBeActive() { ? /* ? ? ? 观察者是否活跃就等于mOwner的状态是否大于等于STARTED; ? ? ? 如果页面当前不可见,你发送了一条消息,此时是不会被分发的, ? ? ? 可以避免后台任务抢占资源,当页面恢复可见才会分发。 ? ? ? */ ? ? ? return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED); ? } ? // Activity/Fragment的生命周期变化会回调此方法。 ? @Override ? public void onStateChanged(@NonNull LifecycleOwner source, ? ? ? ? ? @NonNull Lifecycle.Event event) { ? ? ? Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState(); ? ? ? // 如果当接收到DESTROYED的事件会自动解除跟owner的绑定,避免内存泄露 ? ? ? if (currentState == DESTROYED) { ? ? ? ? ? removeObserver(mObserver); ? ? ? ? ? return; ? ? ? } ? ? ? Lifecycle.State prevState = null; ? ? ? while (prevState != currentState) { ? ? ? ? ? prevState = currentState; ? ? ? ? ? //说明宿主的状态发生了变化,此时会判断宿主是否处于活跃状态 ? ? ? ? ? activeStateChanged(shouldBeActive()); ? ? ? ? ? currentState = mOwner.getLifecycle().getCurrentState(); ? ? ? } ? } ? ? @Override ? boolean isAttachedTo(LifecycleOwner owner) { ? ? ? return mOwner == owner; ? } ? ? @Override ? void detachObserver() { ? ? ? mOwner.getLifecycle().removeObserver(this); ? } } 4.3 ObserverWrapper状态变更后,如果观察者处于活跃状态会触发数据的分发流程 private abstract class ObserverWrapper { ? final Observer<? super T> mObserver; ? boolean mActive; ? //ObserverWrapper在每次注册的时候都会重新new,所以mLastVersion每次都是-1开始。 ? 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; ? ? ? } ? ? ? // immediately set active state, so we'd never dispatch anything to inactive ? ? ? // owner ? ? ? mActive = newActive; ? ? ? // 更新活跃值 活跃1 非活跃-1 ? ? ? changeActiveCounter(mActive ? 1 : -1); ? ? ? if (mActive) { ? ? ? // 如果是活跃状态,分发值 ? ? ? ? ? dispatchingValue(this); ? ? ? } ? } } changeActiveCounter 方法代码如下: @MainThread void changeActiveCounter(int change) { // 上一次的活跃数 ? int previousActiveCount = mActiveCount; ? // 当前活跃数 ? mActiveCount += change; ? if (mChangingActiveState) { ? ? ? return; ? } ? mChangingActiveState = true; ? try { ? ? ? while (previousActiveCount != mActiveCount) { ? ? ? ? ? // 从不活跃变为活跃状态,需要回调 onActive方法 ? ? ? ? ? boolean needToCallActive = previousActiveCount == 0 && mActiveCount > 0; ? ? ? ? ? // 从活跃状态变为不活跃状体,需要回调onInactive方法 ? ? ? ? ? boolean needToCallInactive = previousActiveCount > 0 && mActiveCount == 0; ? ? ? ? ? previousActiveCount = mActiveCount; ? ? ? ? ? if (needToCallActive) { ? ? ? ? ? ? ? onActive(); ? ? ? ? ? } else if (needToCallInactive) { ? ? ? ? ? ? ? onInactive(); ? ? ? ? ? } ? ? ? } ? } finally { ? ? ? mChangingActiveState = false; ? } } dispatchingValue(this)数据分发流程控制:(内部执行considerNotify(initiator)方法),这个方法我们后面分析。 4.4 setValue 发送数据源码分析postValue 最终也是调用 setValue 方法,这里就不做分析了,我们主要分析 setValue 方法,代码如下: @MainThread ? protected void setValue(T value) { ? ? ? assertMainThread("setValue"); ? ? ? // 这个mVersion是属于LiveData的,然后只在setValue ? ? ? // (postValue最终也会调用setValue)的时候会自增1 ? ? ? mVersion++; ? ? ? // 保存这次变化的数据 ? ? ? mData = value; ? ? ? // 分发数据 ? ? ? dispatchingValue(null); ? } 接下来我们具体分析 dispatchingValue 方法,代码如下: @SuppressWarnings("WeakerAccess") /* synthetic access */ void dispatchingValue(@Nullable ObserverWrapper initiator) { ? if (mDispatchingValue) { ? ? ? mDispatchInvalidated = true; ? ? ? return; ? } ? //进入while循环前,设置为true,如果此时另外一个数据发生变化,到了此函数中就直接在上面返回了 ? mDispatchingValue = true; ? do { ? //开始for循环前,设置为false,for循环完,也会退出while循环 ? ? ? mDispatchInvalidated = false; ? ? ? if (initiator != null) { ? ? ? // 如果传递的观察者不为空,则把数据分发给他自己。 ? ? ? // 这个流程是Activity/Fragment的生命周期发生变化的时候会被触发 ? ? ? ? ? considerNotify(initiator); ? ? ? ? ? initiator = null; ? ? ? } else { ? ? ? // 遍历集合中所有已注册的的观察者,逐个调用considerNotify,分发数据 ? ? ? ? ? for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator = ? ? ? ? ? ? ? ? ? mObservers.iteratorWithAdditions(); iterator.hasNext(); ) { ? ? ? ? ? ? ? considerNotify(iterator.next().getValue()); ? ? ? ? ? ? ? //这里mDispatchInvalidated 为true,表示在while循环未结束的时候, ? ? ? ? ? ? ? // 有其他数据发生变化,并调用了该函数 ? ? ? ? ? ? ? //在上面的if判断中设置了 mDispatchInvalidated = true, ? ? ? ? ? ? ? // 结束本次for循环,没有退出while循环,开始下一次for循环 ? ? ? ? ? ? ? if (mDispatchInvalidated) { ? ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? ? } ? ? ? ? ? } ? ? ? } ? } while (mDispatchInvalidated); ? //退出while 后,设置为false,正常处理数据变化 ? mDispatchingValue = false; } 这里有两个变量
看下considerNotify 的函数,调用了之前 LiveData 设置的 observer 的 onChanged 函数,代码如下: 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. ? // 如果当前的生命周期是非活跃,就不回调onChanged函数, ? // 在LifecycleBoundObserver 中记录状态,当生命周期变为活跃,就回去更新数据 ? if (!observer.shouldBeActive()) { ? ? ? observer.activeStateChanged(false); ? ? ? return; ? } ? // 此处判断观察者接收消息的次数是否大于等于 发送消息的次数(observer被创建之初verison=-1 ) ? if (observer.mLastVersion >= mVersion) { ? ? ? return; ? } ? observer.mLastVersion = mVersion; ? // 这里会执行传入的observer的onChanged方法 ? observer.mObserver.onChanged((T) mData); } 综上分析:LiveData的粘性事件:
这种情况被称为LiveData的粘性事件 扫描下方二维码关注公众号,获取更多技术干货。? |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 9:08:06- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |