Android View post 方法
解析View.post方法。分析一下这个方法的流程。
说起post方法,我们很容易联想到Handler的post方法,都是接收一个Runnable对象。那么这两个方法有啥不同呢?
Handler的post方法
先来简单看一下Handler的post(Runnable)方法。这个方法是将一个Runnable加到消息队列中,并且会在这个handler关联的线程里执行。
下面是关联的部分源码。可以看到传入的Runnable对象,装入Message后,被添加进了queue队列中。
Handler 有关的部分源码
// android.os Handler 有关的部分源码
public final boolean post(@NonNull Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
具体流程,可以看handler介绍
View的post方法
我们直接跟着post的源码走。
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
// Postpone the runnable until we know on which thread it needs to run.
// Assume that the runnable will be successfully placed after attach.
getRunQueue().post(action);
return true;
}
private HandlerActionQueue getRunQueue() {
if (mRunQueue == null) {
mRunQueue = new HandlerActionQueue();
}
return mRunQueue;
}
可以看到一开始就查询是否有attachInfo,如果有,则用attachInfo.mHandler来执行这个任务。
如果没有attachInfo,则添加到View自己的mRunQueue中。确定运行的线程后,再执行任务。
post(Runnable action)的返回boolean值,如果为true,表示任务被添加到消息队列中了。
如果是false,通常表示消息队列关联的looper正在退出。
那么我们需要了解AttachInfo和HandlerActionQueue。
AttachInfo
AttachInfo是View的静态内部类。View关联到父window后,用这个类来存储一些信息。
AttachInfo存储的一部分信息如下:
WindowId mWindowIdwindow的标志View mRootView最顶部的viewHandler mHandler这个handler可以用来处理任务
HandlerActionQueue
当View还没有handler的时候,拿HandlerActionQueue来缓存任务。HandlerAction是它的静态内部类,存储Runnable与延时信息。
public class HandlerActionQueue {
private HandlerAction[] mActions;
public void post(Runnable action)
public void executeActions(Handler handler)
// ...
private static class HandlerAction {
final Runnable action;
final long delay;
// ...
}
}
View的mRunQueue
将任务(runnable)排成队。当View关联上窗口并且有handler后,再执行这些任务。
/**
* Queue of pending runnables. Used to postpone calls to post() until this
* view is attached and has a handler.
*/
private HandlerActionQueue mRunQueue;
这个mRunQueue里存储的任务啥时候被执行?我们关注dispatchAttachedToWindow方法。
void dispatchAttachedToWindow(AttachInfo info, int visibility) {
// ...
// Transfer all pending runnables.
if (mRunQueue != null) {
mRunQueue.executeActions(info.mHandler);
mRunQueue = null;
}
// ...
}
这个方法里调用了mRunQueue.executeActions。
executeActions(Handler handler)方法实际上是用传入的handler处理队列中的任务。
而这个dispatchAttachedToWindow会被ViewGroup中被调用。
或者是ViewRootImpl中调用
host.dispatchAttachedToWindow(mAttachInfo, 0);
小结
View的post方法,实际上是使用了AttachInfo的handler。
如果View当前还没有AttachInfo,则把任务添加到了View自己的HandlerActionQueue队列中,然后在dispatchAttachedToWindow中把任务交给传入的AttachInfo的handler。也可以这样认为,View.post用的就是handler.post。
我们在获取View的宽高时,会利用View的post方法,就是等View真的关联到window再拿宽高信息。
流程图归纳如下

更多请参见Android合集的最近更新
Android View post 方法的更多相关文章
- [转]Android View.onMeasure方法的理解
转自:http://blog.sina.com.cn/s/blog_61fbf8d10100zzoy.html Android View.onMeasure方法的理解 View在屏幕上显示出来要先经过 ...
- Android View.onMeasure方法的理解
View在屏幕上显示出来要先经过measure(计算)和layout(布局).1.什么时候调用onMeasure方法? 当控件的父元素正要放置该控件时调用.父元素会问子控件一个问题,“你想要用多大地方 ...
- [转载]Android View.onMeasure方法的理解
2013-12-18 10:56:28 转载自http://blog.sina.com.cn/s/blog_61fbf8d10100zzoy.html View在屏幕上显示出来要先经过measure( ...
- Android View.onMeasure方法的理解(转载)
一下内容转载自http://blog.sina.com.cn/s/blog_61fbf8d10100zzoy.html View在屏幕上显示出来要先经过measure(计算)和layout(布局).1 ...
- Android View各种尺寸位置相关的方法探究
Android View各种尺寸位置相关的方法探究 本来想做一个View间的碰撞检测之类的. 动手做了才发现不是想象的那么简单. 首先,写好了碰撞检测的工具类如下: package com.mengd ...
- Android View中的控件和监听方法...
PS:居然三天没写博客了...今天补上...东西虽多,但是都是一些基础...代码多了一些,有人可能会这样问,粘这么多代码有毛用..其实对于一个Android的初学者来说,一个完整的代码是最容易帮助理解 ...
- Android view中的requestLayout和invalidate方法
Android view中的requestLayout和invalidate方法 requestLayout:当view确定自身已经不再适合现有的区域时,该view本身调用这个方法要求parent v ...
- android view的setVisibility方法值的意思
android view的setVisibility方法值的意思 有三个值 visibility One of VISIBLE, INVISIBLE, or GONE. 常量值为0,意思是可见的 常 ...
- Android编程动态创建视图View的方法
在Android开 发中,在Activity中关联视图View是一般使用setContentView方法,该方法一种参数是使用XML资源直接创 建:setContentView (int layout ...
随机推荐
- 列出文件夹中分级目录java
package test; import java.io.File; public class exportFileName { public static void main(String[] ar ...
- 神经网络:numpy实现神经网络框架
欢迎访问个人博客网站获取更多文章: https://beityluo.space 本文用numpy从零搭建了一个类似于pytorch的深度学习框架 可以用于前面文章提到的MINST数据集的手写数字识别 ...
- 蓝桥杯练习-各大OJ平台介绍
校赛准备的不够充分,简单题失分太遗憾, 有幸参加到省赛,这次先码一下练习平台,等学期结束忙完之后好好练习! 1.题库与网站资源题库-在线提交系统(Online Judge)简介 下面是几个比较大的 ...
- Windows内核开发-6-内核机制 Kernel Mechanisms
Windows内核开发-6-内核机制 Kernel Mechanisms 一部分Windows的内核机制对于驱动开发很有帮助,还有一部分对于内核理解和调试也很有帮助. Interrupt Reques ...
- MATLAB—面向复数和数组的基本运算
文章目录 一.MATLAB基本运算说明 二.面向复数的计算特点 1.基础知识 2.对复数的基本操作 3.复数的开方问题 二.面向数组 1.数组的输入形式 2.对矩阵中的元素进行并行操作 3.利用数组运 ...
- 数字化转型:敏捷和DevOps如何降低风险,提高速度
进行数字化转型就意味着团队需要应对经常发生冲突的挑战--例如,要应对在复杂的相互依赖环境中快速变化的需求.对软件开发人员来说,这是一个熟悉的困境. 如果使用传统的瀑布方法来应对这些挑战,就会发现,在线 ...
- Longhorn,企业级云原生容器分布式存储 - 高可用
内容来源于官方 Longhorn 1.1.2 英文技术手册. 系列 Longhorn 是什么? Longhorn 企业级云原生容器分布式存储解决方案设计架构和概念 Longhorn 企业级云原生容器分 ...
- ubuntu20.04 apache2 配置安装ssl证书
1. 获取SSL证书 根据自己的网站服务器来获取不同的ssl证书,我的服务器是ubuntu20.04. 证书如下: 00_***.key ## 私钥文件 01_CERTIFICATE_***_***. ...
- 备战秋招之十大排序——O(n^2)级排序算法
一.冒泡排序 冒泡排序是入门级的算法,但也有一些有趣的玩法.通常来说,冒泡排序有三种写法: 一边比较一边向后两两交换,将最大值 / 最小值冒泡到最后一位: 经过优化的写法:使用一个变量记录当前轮次的比 ...
- 1、Task的优势
1.Task的优势 ThreadPool相比Thread来说具备了很多优势,但是ThreadPool却又存在一些使用上的不方便.比如: ◆ ThreadPool不支持线程的取消.完成.失败通知等交互性 ...