

runOnUiThread 、Handler.post、View.post 有什么区别?(解决篇)
source link: https://mp.weixin.qq.com/s?__biz=MjM5OTE4ODgzMw%3D%3D&mid=2247483722&idx=1&sn=7290f6eefc0ef19d933c0b4039865bcb&chksm=a73e01449049885220395c4906f6293900a7bb51fc2f509643839f3c41440a51ddae01d9eb56&mpshare=1
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

runOnUiThread 、Handler.post、View.post 有什么区别?(解决篇)
Original 巴掌 巴巴巴掌 2017-12-12 23:30 Posted on
该文章已经收集到面试题整理(可在首页点击底部 Tab 看到)。
在上篇公众号文章中,我提了一个问题,如下图:
想得到答案,就得知道 runOnUiThread 、Handler.post、View.post 三者的区别。
从难易程度来讲,我们先说下 runOnUiThread 和 Handler.post 的区别,先看看 runOnUiThread 的源码:
如果当前不是 UI 线程,那么由主线程的 Handler 扔个消息给 MessageQueue;如果当前是 UI 线程,则立刻执行。
知道这样的话,之前的那个题目就能回答一部分了,【234】的顺序应该是【324】,因为第一个 runOnUiThread 会立刻执行,而【24】就依据进入 MessageQueue 的先后顺序执行。
相信给【234】排序应该大部分人都错不了,那么第一个 View.post 呢?这个就略坑了。
题目设了个陷阱大家应该都看到了,View 实例化后并没有被加进任何能 attachToWindow 的 ViewGroup 中,这是一个很大的坑点。
我们先来看看 View.post 的源码,值得注意的是,View.post 的实现从 api24 开始有了变化,也就是说文章最开始的那道题在 Android 7.0(api24)和 7.0 以下的设备上输出的答案会不同。
先看看 api24 上的源码:
再看看 api23 上的源码:
看到区别了吧,当 mAttachInfo 为 null 的时候,源码变了。
我们先分析下相同部分的代码,也就是当 mAttachInfo 不为 null 的情况,我们看看它是啥时候被赋值的:
View#dispatchAttachedToWindow
再看看 View 的dispatchAttachedToWindow 是哪位哥哥调的,显然是 ViewGroup:
ViewGroup#dispatchAttachedToWindow
那么这个 ViewGroup 是谁?又是谁调用的?
先来看看是谁调用的:
ViewRootImpl#performTraversals
调用方知道了,那么 host 是谁?host 其实就是 Activity 的 DecorView,再往下就不在这篇文章里扯了,我们只要知道,要想让子 View 能调用 dispatchAttachedToWindow,那么一定得是 DecorView 的子 View,而我们【1】中创建的 View 并不是 DecorView 的子 View,因此【1】中的 View 的 dispatchAttachedToWindow 方法并不会被执行到,所以最开始说的 mAttachInfo 在我们这道题里是为 null 的。
理了半天,只是把 api23 和 api23 以上相同部分的源码解释了下,那么不相同的源码呢?也就是当 mAttachInfo 为 null 的情况,别急,慢慢道来。
上面说了,我们【1】的例子就会使 mAttachInfo 为 null,在 api23 及以下就会执行 ViewRootImpl.getRunQueue().post(action); 而 api24 开始会执行 getRunQueue().post(action); 。
来看看两者的区别,api23 中是使用的 ViewRootImpl 的 RunQueue:
sRunQueues 是个静态的 ThreadLocal 对象,关于 ThreadLocal 也是面试常问题,之后单开文章讲解,这里要知道的就是,主线程用的是同一个 RunQueue,这个 RunQueue 里的 Runnable 啥时候会执行?
ViewRootImpl#performTraversals
performTraversals 方法是整个 View 的绘制流程的开始,走到这里时,api23 及一下的 View.post 代码会执行,也就是题目中的答案在 api23 及以下设备会是【3241】,那么 api24 以后呢?直接使用 View 里的 getRunQueue:
他已经不是使用的主线程 RunQueue,而是自己这个对象里的,那自己的 RunQueue 啥时候执行呢?之前说了,在 dispatchAttachedToWindow 里会执行到,而【1】的 View 并不会执行 dispatchAttachedToWindow,也就是说在 api24 开始题目的答案是 【324】。
全部分析完了,正确答案应该是【324】/【3241】,需要区分 api 版本。有不少朋友留言给出了自己的答案,感谢大家的参与,希望这个分析对大家能有帮助。
Recommend
-
107
HTTP - @okzpy9425 - 前几天去面试,被问道一个这样的问题。。 我回答的是主要区别是 一个是幂等的 一个不是。然后他说还有其他。我一时半会儿也没想出来。。然后就 GG 了。
-
59
-
41
0. 前言 做 Android 开发肯定离不开跟 Handler 打交道,它通常被我们用来做主线程与子线程之间的通信工具,而 Handler 作为 Android 中消息机制的重要一员也确实给我们的开发带来了极大的便利。 可以说只要有异步线程与主线程通信的地方
-
32
第一次在掘金上写东西,萌新表示现在瑟瑟发抖,哪里说得不对还望各位大佬纠正┓( ´∀` )┏ 最直观的就是语义上的区别 get用来获取数据,post用来提交数据 get参数有长度限制(受限于url长度,具体的数值取决于浏览器和服务器的限
-
38
解题思路:这道题已经属于不能再考的题目了,遇到这道题目。我们不能简单的解答,get如何,post如何。我们需要从两者的不同点、相同点、数据的传输方式、底层分析。 相同点: 两者都是基于tcp协议进行传输数据的,都是h...
-
13
基于对象可达性原理解决Handler引起内存泄露问题58同城 Android工程师这篇文章是刚工作不久时分享的,今天整理文档时发现了,今天把它整理到知乎上。记录工作中曾经做过哪些事情,...
-
4
GET 和 POST 是 HTTP 请求中最常用的两种请求方法,在日常开发的 RESTful 接口中,都能看到它们的身影。而它们之间的区别,也是一道常见且经典的面试题,所以我们本文就来详细的聊聊。 HTTP 协议定义的方法类型总共有以下 10 种...
-
8
刚开始接触 Kubernetes 时,你学到的第一件事就是每个 Pod 都有一个唯一的 IP 和主机名,并且在同一个 Pod 中...
-
13
SAP ABAP CDS view 里 INNER JOIN 和 Association 的区别 推荐 原创 JerryWang汪子熙...
-
6
HTTP最早被用来做浏览器与服务器之间交互HTML和表单的通讯协议;后来又被被广泛的扩充到接口格式的定义上。所以在讨论GET和POST区别的时候,需要现确定下到底是浏览器使用的GET/POST还是用HTTP作为接口传输协议的场景。 浏览器的GET和POST
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK