Android UI线程

 我来答
大沈他次苹0B
2022-06-23 · TA获得超过7257个赞
知道大有可为答主
回答量:3059
采纳率:100%
帮助的人:169万
展开全部

思考:

先必须了解下面2个问题
1.顾名思义 UI线程 就是刷新UI 所在线程
2.UI是单线程刷新

1.对Activity 来说 UI线程就是其主线程
2.对View来说 UI线程就是创建ViewRootImpl所在的线程
可以通过 WindowManager 内部会创建ViewRootImpl对象

好了,进入主题。我们来慢慢揭开面纱。
我们可以分别从几个方面切入

我们可能都有使用过 runOnUiThread 现在来看看的源码实现。

可以从上面的源码 看到
不是UI线程 就用Handler切到Handler所在的线程中,如果是UI线程直接就调用run方法。

Activity的创建:
1.Activity创建:mInstrumentation.newActivity
2.创建Context :ContextImpl appContextcreateBaseContextForActivity(r)

我们经常用这个方法干的事情就是,要么在onCreate中获取View宽高的值。要么就是在子线程中做一些耗时操作 ,然后post切到对应View所在的线程 来绘制UI操作。那么这个对应的线程就是UI线程了。
那么这个UI线程就一定是主线程吗?
接来继续来看。它的源码View:post

mAttachInfo 在dispatchAttachedToWindow 中被赋值 ,也就是在ViewRootImpl创建的时候,所以是创建ViewRootImpl所在的线程。
attachInfo 上面时候为null 呢?在ViewRootImpl 还没来得及创建的时候,ViewRootImpl 创建是在 “onResume" 之后。所以在 Activity 的 onCreate 去View.post 那么AttachInfo 是为null 。
当 AttachInfo == null 那么会调用 getRunQueue().post(action) 。
最终这个Runnable 被 缓存到 HandlerActionQueue 中。
直到ViewRootImpl 的 performTraversals 中 调用dispatchAttachedToWindow(mAttachInfo, 0);, 那么才会去处理 RunQueue() 中的Runnable。

来张图 便于理解这个流程

我们有时候去子线程操作UI的时候(如:requestLayout),会很经常见到下面的 报错日志:
Only the original thread that created a view hierarchy can touch its views

为什么会报这个错误呢?
翻译一下:只有创建视图层次结构的原始线程才能接触到它的视图。
也就是操作UI的线程要和ViewRootImpl创建的线程是同一个线程才行,并不是只有主线程才能更新UI啊。
ViewRootImpl创建的线程?那么 ViewRootImpl 在哪里被创建的呢?

从上图可以看到ViewRootImpl创建最开始是从 ActivityThread 的HandleResumeActivity中开始 一直 ViewRootImpl 创建,也就是说ViewRootImpl 对应的UI线程和 ActivityThread 在同一个线程 也就是主线程。

好了 通过上面的讲解,上面的问题相信你可以自己回答啦~

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式