刚学习Android开发的时候经常有需要在子线程里更新UI的操作,总是会遇到报错:Only the original thread that created a view hierarchy can touch its views.
“只有创建视图层次结构的原始线程才能触摸其视图。”
因为大部分的View创建都是在UI线程(主线程),所以我们都有一个共识:只有在UI线程中才能够更新UI
那为什么呢?
当我们遇到Only the original thread that created a view hierarchy can touch its views.
的时候,可以看到报错的路径是:at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7905)
说明ViewRootImpl
这个类对当前线程是否为主线程进行了判断:
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}
ViewRootIml
的checkThread
方法里,通过判断
mThread != Thread.currentThread()
如果当前没有在UI线程,就会抛出异常
那有没有在子线程中可以更新UI的操作呢?
这里放出一段代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = findViewById(R.id.textView);
new Thread(new Runnable() {
@Override
public void run() {
tv.setText("子线程更新UI测试");
}
}).start();
}
这样操作是可以改变TextView的Text属性并且没有报错的。
通过上面的了解可以推断,这个时候没有进入ViewRootImpl
的checkThread
方法,逃过一劫,具体原因我们可以从源码入手。这里贴一下讲的很好的链接。
结论:从源码分析可得知,ViewRootImpl
对象是在onResume
方法回调之后才创建,那么就说明了为什么在生命周期的onCreate
方法里,甚至是onResume
方法里都可以实现子线程更新UI,因为此时还没有创建ViewRootImpl
对象,并不会进行是否为主线程的判断;
总结:
ViewRootImpl
中有checkThread
方法,如果当前线程不是UI线程会抛出异常ViewRootImpl
在Activity启动流程中的OnResume()
方法被创建归根到底这个问题可以从Android的启动流程来分析,Android启动时,先进行OnCreate
的回调,然后进行OnResume
,这个时候ViewRootImpt
还没有进行创建初始化,所以我们在OnCreate
中在子线程更新UI是可行的。
文章浏览阅读693次。中文名称:计算机科学经典著作英文名称:Computer Science版本:简介:The Art of Computer Programming Author: Donald.E.Knuth Book Info: 这部书被誉为20世纪最重要的20部著作之一,与Einstein的"相对论"并列,是计算机科学领域的权威著作.全书共分7卷,目前已经出版了3卷,被誉为"计算
文章浏览阅读399次。4、SPSSAU输出结果此表格展示出典型变量的提取情况,上表中共显示有5个典型变量被提取出来,在进行F检验时显示,其中仅2个典型变量是呈现出0.01水平的显著性,因此,最终应该以两个典型变量为准进行后续研究。并且第一个典型变量的相关系数值为0.763,第二个典型变量为0.706,相关系数值较高,说明典型变量之间有着紧密的正向相关关系。此步骤非常重要,共提取出2个典型变量,并且直接得出典型变量对的相..._spss26典型相关性在哪
文章浏览阅读237次。Mac 在国内很受欢迎,尤其是在IT 人员圈子里,更是iOS开发者的专宠。普通用户喜欢 Mac 可以理解,毕竟 Mac 设计美观,简单好用,没有病毒。那么为什么专业人士也对 Mac 情有独钟呢?从一位开发者使用5念经验来看应该有下面几个原因: 开发环境 c/c++/java/perl/py...
文章浏览阅读567次。微信小程序利用页面跳转方式传值:例如:在页面中有这样一个遍历渲染的结构:<view bindtap="goDetails" data-index="{{index}}" class="conver-item" wx:key="list" wx:for="{{ list }}"> <image class="convert-img" src="{{item.img}}"></image> <view class="convert-txt"> &
文章浏览阅读3.1k次,点赞4次,收藏8次。第一步:点在setting第二步:点开对应的项目栏第三步:找到对应需要添加的按钮第四步:点击apply效果对比觉得本文章对您有帮助,那么可以选择打赏。打赏多少,您高兴就行,谢谢您对我的支持! ~(@^_^@)~ 微信扫一扫..._idea2019版本中tool window里面的工具如何新增
文章浏览阅读788次。1. SIP开发环境的搭建http://www.rosoo.net/a/201007/9819.html要在windows或者linux平台下开发基于SIP的软电话,需要以下软件服务器端软件: 注册多个客户端到服务器上,可以进行通话测试SIP客户端软件:主要用于测试,可以对别人已经完成的客户端进行抓包,以比对自己程序的发包数据SIP协议栈:基于某个现成的SI_lumisoft.sip.message
文章浏览阅读189次。加油的小路上如今算法的应用是相当的广泛,无论是项目开发,还是系统架构,还有应用最多的人工智能,在互联网行业激烈竞争的当下,不了解算法,都不好意思说自己是个coder或者程序猿。在LeetCode爬梯过程中,一个问题死活敲不出来,苦思冥想,最终还是去见了度娘,网上的大神很多,在查阅的结果中好多都是几年前的,从中翻出来一个2019年6月份的一个还差不多的思路,该博主把编码的耗时结果放了上去,如下图:时间的改变于是根据该博主的思路和源码,进行输入测试的时候,执行是没有问题的,但是通过自己提交发现的结果让我
文章浏览阅读160次,点赞2次,收藏3次。本文是对整个Linux系统移植的讲解,适宜有一定基础的初学者进行复习,基本可以自己制作PCB之后自己根据这个方法烧写Linux系统,不涉及U-Boot与Linux的源码和编译流程的讲解(这东西后面再学没事的),只讲最实用的方法,如果你有跟着烧写过一遍Linux系统,那么本文会让你重新复习一遍整个流程,加深对Linux系统移植的理解与应用。
文章浏览阅读2.6k次,点赞2次,收藏4次。出于数学太差的原因,这段时间要集中加强学习,突然发现正态分布这个东西很难理解,看书不起作用,强迫用自己的理解去解释它,望讲清楚了就理解清楚了。根据π与e的关系,通过一番证明我们可以得到:我们把上面积分号内的式子看成函数f(x),实际上我们经常见到的式子是取,根据坐标变换有把积分号内的新式子看成f(x)我们就得到了1维正态分布的原形函数,只要同样用平移和缩放的坐标变换,我们...
文章浏览阅读414次。指向类数据成员、类成员函数的指针(非静态)#include "stdafx.h"#include using namespace std;#include #if 0----指向类 数据成员的指针 实际上是指向类的定义::*赋值&初始化::*[=&::]指向类成员指针小结:与普通意义上的指针不一样。存放的是偏移量。从类的起始地址的偏移量指向非静态成员函数
文章浏览阅读544次。2、贝叶斯网络贝叶斯网络,由一个有向无环图(DAG)和条件概率表(CPT)组成。 贝叶斯网络通过一个有向无环图来表示一组随机变量跟它们的条件依赖关系。它通过条件概率分布来参数化。每一个结点都通过P(node|Pa(node))来参数化,Pa(node)表示网络中的父节点。如图是一个简单的贝叶斯网络,其对应的全概率公式为:P(a,b,c)=P(c∣a,b)P(b∣a)P(a)P(a,b,c)=P(c...
文章浏览阅读313次。近日,在上海召开的2018年世界人工智能大会(2018 WAIC),吸引了来自全球的人工智能顶尖科学家、中外院士、百位国内外龙头企业CEO。本届大会主要从技术、产业、应用...