| |
|
|
开发:
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图书馆 购物 三丰科技 阅读网 日历 万年历 2025年11日历 | -2025/11/21 2:53:56- |
|
| 网站联系: qq:121756557 email:121756557@qq.com IT数码 |