当前位置:网站首页>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的机制。
边栏推荐
- 一文读懂数仓中的pg_stat
- 回归测试的分类
- Es log error appreciation -maximum shards open
- Computer win7 system desktop icon is too large, how to turn it down
- Es log error appreciation -- allow delete
- leetcode:648. Word replacement [dictionary tree board + find the shortest matching prefix among several prefixes]
- Bill Gates posted his resume 48 years ago: "it's not as good-looking as yours."
- 2022PAGC 金帆奖 | 融云荣膺「年度杰出产品技术服务商」
- 全球首款 RISC-V 笔记本电脑开启预售,专为元宇宙而生!
- Data connection mode in low code platform (Part 2)
猜你喜欢
Cocoscreator operates spine for animation fusion
Navigation - are you sure you want to take a look at such an easy-to-use navigation framework?
Leetcode one question per day (636. exclusive time of functions)
[today in history] July 7: release of C; Chrome OS came out; "Legend of swordsman" issued
Pinduoduo lost the lawsuit, and the case of bargain price difference of 0.9% was sentenced; Wechat internal test, the same mobile phone number can register two account functions; 2022 fields Awards an
C 6.0 language specification approved
WebRTC 音频抗弱网技术(上)
Xiaomi's path of chip self-development
小程序目录结构
华为云数据库DDS产品深度赋能
随机推荐
Navigation — 这么好用的导航框架你确定不来看看?
Pinduoduo lost the lawsuit, and the case of bargain price difference of 0.9% was sentenced; Wechat internal test, the same mobile phone number can register two account functions; 2022 fields Awards an
Read PG in data warehouse in one article_ stat
拼多多败诉,砍价始终差0.9%一案宣判;微信内测同一手机号可注册两个账号功能;2022年度菲尔兹奖公布|极客头条...
[Yugong series] go teaching course 005 variables in July 2022
2022年13个UX/UI/UE最佳创意灵感网站
PD虚拟机教程:如何在ParallelsDesktop虚拟机中设置可使用的快捷键?
Stm32cubemx, 68 sets of components, following 10 open source protocols
asp. Netnba information management system VS development SQLSERVER database web structure c programming computer web page source code project detailed design
How bad can a programmer be? Nima, they are all talents
In the field of software engineering, we have been doing scientific research for ten years!
Navigation - are you sure you want to take a look at such an easy-to-use navigation framework?
Mlgo: Google AI releases industrial compiler optimized machine learning framework
什么是云原生?这回终于能搞明白了!
MicTR01 Tester 振弦采集模块开发套件使用说明
Pytorch model trains practical skills and breaks through the bottleneck of speed
LeetCode 648. Word replacement
《微信小程序-进阶篇》组件封装-Icon组件的实现(一)
内部排序——插入排序
PAG体验:十分钟完成AE动效部署上线各平台!