Android可不可以在子线程中更新UI?

开发者 2024-9-11 17:04:12 87 0 来自 中国
我们起首来看一段代码:
在一个activity的xml文件中任意写一个TextView文本控件,然后在Activity的onCreate方法中开启一个子线程并在该子线程的run方法中更新TextView文本控件,你会发现根本没有任何标题。
但是如果你把Thread.sleep(2000)放开绘发现报错瓦解:
我们从这堆栈开始分析源码缘故因由:
mButton.setText("woyaoniu");会调用android.widget.TextView#checkForRelayout方法中来,checkForRelayout继承调用android.view.View#requestLayout这里来:
我们来mParent是什么,起首它是一个ViewParent接口,requestLayout()是接口中界说的一个方法:
但是完整实现类却在View中,而不是ViewGroup中 固然是ViewGroup实现了ViewParent接口




6.png 接着我们去看下View中mParent的来源:
View中的mParent成员变量通常来说指的就是当前View的父容器ViewGroup,但有一个特殊就是,对于顶层decorView来说它的mParent是ViewRootImpl。下面我们看源码来证明:




8.png mParent通过方法assignParent(ViewParent parent)被赋值:
1 在ViewRootImpl中的setView方法中设置通报过来的DecorView,在该方法中会给DecorView中的mParent指定为当前ViewRootImpl,而且ViewRootImpl实现了ViewParent接口。
9.png 2 将View添加到ViewGroup中,通常使用addView(View child)等方法,最后会调用内部的addViewInner方法,将添加进来的子View的mParent设置为当前所在容器:
那么从调用android.view.View#requestLayout不停往上调用,最后会执行到ViewRootImpl#requestLayout方法


至此这个调用分析链报错就可以到这了。下面再看为啥解释掉Thread.sleep(2000)就没有报错呢:
根本缘故因由就是ViewRootImpl到底是在哪初始化的呢!ViewRootImpl是在onResume中初始化的,而我们开启的子线程是在onCreate中,这个时间步伐还没有去检测当火线程是不是主线程,以是就没有抛非常,下面我们去看ActivityThread源码,找出缘故因由:


您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 20:23, Processed in 0.185291 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表