皮皮网

【android 源码编译adb】【ofed源码解读】【tree统计源码】runonuithread 源码

2024-11-18 04:47:45 来源:金融 培训 网站源码

1.Android UI线程

runonuithread 源码

Android UI线程

        思考:

        先必须了解下面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,android 源码编译adb 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 在同一个线程 也就是主线程。

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