当前位置:网站首页>Andriod --- JetPack :LiveData setValue 和 postValue 的区别
Andriod --- JetPack :LiveData setValue 和 postValue 的区别
2022-07-07 12:48:00 【梁同学与Android】
文章内容来自:https://blog.csdn.net/catzifeng/article/details/103931517
Andriod — JetPack :LifeCycle 的诞生
Andriod — JetPack :ViewModel 的诞生
Andriod — JetPack :BaseObservable 与 ObservableField 双向绑定
Andriod — JetPack :DataBinding + LiveData +ViewModel 简单实例
Andriod — JetPack :Room + ViewModel + LiveData 增删改查实例
Andriod — JetPack :LiveData setValue 和 postValue 的区别
平时我们使用LiveData的时候,需要更新数据的时候,LiveData提供了两种更新数据的方式:
- setValue(T value)
- postValue(T value)
那么这两种方式有什么区别呢?
结论
setValue()只能在主线程中调用,postValue()可以在任何线程中调用。
setValue()
我们先不急着看源码,先看官方如何介绍这个方法。
/** * Sets the value. If there are active observers, the value will be dispatched to them. * <p> * This method must be called from the main thread. If you need set a value from a background * thread, you can use {@link #postValue(Object)} * * @param value The new value */
@MainThread
protected void setValue(T value)
上面的注释已经很清楚了:
这个方法必须在主线程中调用,如果你需要在后台线程中设置value,请移步 #postValue(Object)
更何况人家还用了一个 @MainThread的注解提醒你呢,接下来看源码:
protected void setValue(T value) {
assertMainThread("setValue"); //1
mVersion++; //2
mData = value; //3
dispatchingValue(null); //4
}
private static void assertMainThread(String methodName) {
if (!ArchTaskExecutor.getInstance().isMainThread()) {
throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
+ " thread");
}
}
首先调用 assertMainThread() 方法来判断当前线程是否为主线程(这里他通过一个ArchTaskExecutor的单例类来实现),如果不是主线程,直接抛异常提醒程序员。
如果是在主线程中调用该方法,自加加一个version,来说明值发生了变化。
再把新的值保存起来。
更新value(这个方法不能扯下去,扯下去就是LiveData的源码分析了)。
postValue
我们继续先看一下官方对postValue()的介绍:
/** * Posts a task to a main thread to set the given value. So if you have a following code * executed in the main thread: * <pre class="prettyprint"> * liveData.postValue("a"); * liveData.setValue("b"); * </pre> * The value "b" would be set at first and later the main thread would override it with * the value "a". * <p> * If you called this method multiple times before a main thread executed a posted task, only * the last value would be dispatched. * * @param value The new value */
protected void postValue(T value)
翻译过来就是:
通过任务(Runnable)的方式在主线程中更新数据。
如果同时调用 .postValue(“a”)和.setValue(“b”),一定是值b被值a覆盖。
如果多次调用 .postValue(),只有最后一个值能够被分发(onChanged()被调用)。
再看详细的源码:
protected void postValue(T value) {
boolean postTask; //1
synchronized (mDataLock) {
//2
postTask = mPendingData == NOT_SET; //3
mPendingData = value; //3
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable); //4
}
定义一个 postTask 的布尔值,判断是否要更新。
加个同步锁,因为可能存在多个子线程同时调用 .postValue() 的情况。
通过判断更新的值是否发生变化来对postTask赋值,并且将value赋值给 mPendingData(mPendingData == NOT_SET第一次一定是返回true,之后都是返回false,然后到这个值更新完毕之前的一瞬间会调用mPendingData=NOT_SET,这也是为什么多次调用 postValue()只有最后一个值才有效的原因)。
通过ArchTaskExecutor进行更新,通过方法及参数名字,我们可以猜测这一步干了什么事情:ArchTaskExecutor将一个Runnable对象往主线程里执行,那么mPostValueRunnable执行的环境一定是主线程,接下来我们再看看mPostValueRunnable究竟做了些什么。
因为现在线程已经切换到主线程了,所以他直接就是调用 setValue()
最后
文中有几次出现了ArchTaskExecutor这个东西,这个类其实就是postValue切换至主线程更新的关键它具体的源码实现非常简单,直接是利用了Handler的机制。
边栏推荐
- What is cloud primordial? This time, I can finally understand!
- Leetcode - Sword finger offer 05 Replace spaces
- 比尔·盖茨晒48年前简历:“没你们的好看”
- 什么是云原生?这回终于能搞明白了!
- leetcode:648. 单词替换【字典树板子 + 寻找若干前缀中的最短符合前缀】
- leetcode:648. Word replacement [dictionary tree board + find the shortest matching prefix among several prefixes]
- Spatiotemporal deformable convolution for compressed video quality enhancement (STDF)
- C# 6.0 语言规范获批
- #yyds干货盘点# 解决名企真题:交叉线
- Zhiting doesn't use home assistant to connect Xiaomi smart home to homekit
猜你喜欢
CVPR2022 | 医学图像分析中基于频率注入的后门攻击
《微信小程序-进阶篇》组件封装-Icon组件的实现(一)
leetcode:648. Word replacement [dictionary tree board + find the shortest matching prefix among several prefixes]
大厂做开源的五大痛点
一个程序员的水平能差到什么程度?尼玛,都是人才呀...
2022年13个UX/UI/UE最佳创意灵感网站
拼多多败诉,砍价始终差0.9%一案宣判;微信内测同一手机号可注册两个账号功能;2022年度菲尔兹奖公布|极客头条...
「2022年7月」WuKong编辑器更版记录
Instructions d'utilisation de la trousse de développement du module d'acquisition d'accord du testeur mictr01
How bad can a programmer be? Nima, they are all talents
随机推荐
Zhiting doesn't use home assistant to connect Xiaomi smart home to homekit
Navigation - are you sure you want to take a look at such an easy-to-use navigation framework?
一文读懂数仓中的pg_stat
大厂做开源的五大痛点
GAN发明者Ian Goodfellow正式加入DeepMind,任Research Scientist
2022云顾问技术系列之高可用专场分享会
A laravel background management expansion package you can't miss - Voyager
Navigation - are you sure you want to take a look at such an easy-to-use navigation framework?
Huawei cloud database DDS products are deeply enabled
Oracle Linux 9.0 officially released
Analysis of arouter
Mmkv use and principle
Beginner JSP
In the field of software engineering, we have been doing scientific research for ten years!
属性关键字ServerOnly,SqlColumnNumber,SqlComputeCode,SqlComputed
激光雷达lidar知识点滴
Summary on adding content of background dynamic template builder usage
Small game design framework
FFmpeg----图片处理
EfficientNet模型的完整细节