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 mWindowId
window的标志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调用Zookeeper
watch机制 Zookeeper watch是一种监听通知机制,可以随时监听一些数据的变化,从而实现数据的及时性. Zookeeper所有的读操作getData(), getChildren()和 ...
- jupyter notebook使用python虚拟环境
jupyter指定环境启动 背景 系统环境中安装有jupyter及相关库,因项目需要,新建了一个torch相关的虚拟环境并安装了对应的内容, 此时,想通过系统中的jupyter启动一个可以应用虚拟环境 ...
- Python数学建模系列(一):规划问题之线性规划
@ 目录 前言 线性规划 样例1:求解下列线性规划问题 scipy库求解 样例2:求解下列线性规划问题 pulp库求解 样例3.运输问题 说明 结语 前言 Hello!小伙伴! 非常感谢您阅读海轰的文 ...
- NOIP 模拟 $27\; \rm 牛半仙的妹子序列$
题解 \(by\;zj\varphi\) 明显一道极长上升子序列的题. 直接线段树维护单调栈,最后单调栈求出可以贡献的序列,答案相加就行. Code #include<bits/stdc++.h ...
- vue中常用插件(货币、日期)
货币插件: 价格格式化 // https://github.com/vuejs/vuex/blob/dev/examples/shopping-cart/currency.js const digit ...
- 0x800b010a 证书
无论是装微软的什么应用,只要报这个错误,下载这个证书: http://download.microsoft.com/download/2/4/8/248D8A62-FCCD-475C-85E7-6ED ...
- Nacos集群部署:
Nacos集群部署: 官网: https://nacos.io/zh-cn/docs/cluster-mode-quick-start.html 1: 下载 Nacos1.2.0 链接:http ...
- Flink Data transformation(转换)
Flink Data transformation 算子学习 1.Source:数据源,Flink在流处理和批处理上的source大概有4类: 基于本地集合的source.基于文件的source.基于 ...
- 利用AOP切面打印项目中每个接口的运行情况
1.前言 AOP切面技术,大家应该都听知道,Spring框架的主要功能之一. AOP切面的用途很广,其中一个常见的用途就是打印接口方法的运行日志和运行时间. 日志对于一个项目很是重要,不仅有助于调错, ...
- nginx简介,使用
nginx是什么 nginx是一个开源的,支持高性能,高并发的www服务和代理服务软件. 支持高并发,能支持几万并发连接 资源消耗少,在3万并发连接下开启10个nginx线程消耗的内存不到200M 可 ...