解析View.post方法。分析一下这个方法的流程。

说起post方法,我们很容易联想到Handlerpost方法,都是接收一个Runnable对象。那么这两个方法有啥不同呢?

Handler的post方法

先来简单看一下Handlerpost(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正在退出。

那么我们需要了解AttachInfoHandlerActionQueue

AttachInfo

AttachInfoView的静态内部类。View关联到父window后,用这个类来存储一些信息。

AttachInfo存储的一部分信息如下:

  • WindowId mWindowId window的标志
  • View mRootView 最顶部的view
  • Handler 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方法,实际上是使用了AttachInfohandler

如果View当前还没有AttachInfo,则把任务添加到了View自己的HandlerActionQueue队列中,然后在dispatchAttachedToWindow中把任务交给传入的AttachInfohandler。也可以这样认为,View.post用的就是handler.post

我们在获取View的宽高时,会利用View的post方法,就是等View真的关联到window再拿宽高信息。

流程图归纳如下

更多请参见Android合集的最近更新

Android View post 方法的更多相关文章

  1. [转]Android View.onMeasure方法的理解

    转自:http://blog.sina.com.cn/s/blog_61fbf8d10100zzoy.html Android View.onMeasure方法的理解 View在屏幕上显示出来要先经过 ...

  2. Android View.onMeasure方法的理解

    View在屏幕上显示出来要先经过measure(计算)和layout(布局).1.什么时候调用onMeasure方法? 当控件的父元素正要放置该控件时调用.父元素会问子控件一个问题,“你想要用多大地方 ...

  3. [转载]Android View.onMeasure方法的理解

    2013-12-18 10:56:28 转载自http://blog.sina.com.cn/s/blog_61fbf8d10100zzoy.html View在屏幕上显示出来要先经过measure( ...

  4. Android View.onMeasure方法的理解(转载)

    一下内容转载自http://blog.sina.com.cn/s/blog_61fbf8d10100zzoy.html View在屏幕上显示出来要先经过measure(计算)和layout(布局).1 ...

  5. Android View各种尺寸位置相关的方法探究

    Android View各种尺寸位置相关的方法探究 本来想做一个View间的碰撞检测之类的. 动手做了才发现不是想象的那么简单. 首先,写好了碰撞检测的工具类如下: package com.mengd ...

  6. Android View中的控件和监听方法...

    PS:居然三天没写博客了...今天补上...东西虽多,但是都是一些基础...代码多了一些,有人可能会这样问,粘这么多代码有毛用..其实对于一个Android的初学者来说,一个完整的代码是最容易帮助理解 ...

  7. Android view中的requestLayout和invalidate方法

    Android view中的requestLayout和invalidate方法 requestLayout:当view确定自身已经不再适合现有的区域时,该view本身调用这个方法要求parent v ...

  8. android view的setVisibility方法值的意思

    android view的setVisibility方法值的意思 有三个值 visibility  One of VISIBLE, INVISIBLE, or GONE. 常量值为0,意思是可见的 常 ...

  9. Android编程动态创建视图View的方法

    在Android开 发中,在Activity中关联视图View是一般使用setContentView方法,该方法一种参数是使用XML资源直接创 建:setContentView (int layout ...

随机推荐

  1. docker 安装prometheus和grafna

    一.拉取镜像 docker pull prom/prometheus 二.配置 sudo mkdir /etc/prometheus/ sudo vim /etc/prometheus/prometh ...

  2. DHCP服务-中继代理

    DHCP中继代理(即DHCP Relay Agent)用于转发来自于另一个没有DHCP服务器子网段中客户端的DHCP请求,即当一台DHCP客户端发起请求后,此时DHCP中继代理就会将已经预先定义好的D ...

  3. idea自定义 tags 删除

    idea custom tags 添加后 如何去除 如何去除 custom tags 随便@一些字符串,这时候alt+enter弹出 Add xxx to custom tags, 这时候按有方向键进 ...

  4. NOIP 模拟 6 考试总结

    T1 这道题是一道裸的暴力,考场写挂了 \(5pts\) 原因竟是忘了删注释,难受 题解 T2 这道题是一道启发式合并,没想出来,拿了个暴力分跑了 题解 T3 这道题就是一道数学期望,想出来就水得很, ...

  5. SqlServer 数据库备份到服务器,及删除

    一:备份 1.在数据库管理下 新建一个维护计划,然后下图中点击 标红的按钮 新建计划作业,建好后就可以 SqlServer 代理下的作业里可以看到刚新建的作业. 2.SqlServer 代理下的作业  ...

  6. 如果服务器数据更新了,CDN的数据是怎么及时更新的

    A:cdn一般用来存静态资源.拿网站来说,当用户访问网站时静态资源从cdn加载.cdn向后段源服务器请求资源并缓存,这个请求过程是周期性的,自动的,称为回源. 当你更新了一个文件,现在正巧还没到cdn ...

  7. 快速排序的Partition函数

    1 //数组中两个数的交换 2 static void swap(int[] nums, int pos1, int pos2){ 3 int temp = nums[pos1]; 4 nums[po ...

  8. 前端云原生,以 Kubernetes 为基础设施的高可用 SSR(Vue.js) 渲染微服务初探(开源 Demo)

    背景 笔者在逛掘金的时候,有幸看到掘友狼族小狈开源的 genesis - 一个可以支持 SSR 和 CSR 渲染的微服务解决方案.总体来说思想不错,但是基于 Kubernetes 云原生部署方面一直没 ...

  9. VS在调试桌面程序时,cout到控制台方法

    参考博客:https://blog.csdn.net/xinxinsky/article/details/80733400 C++桌面程序设置 Properties -> Build Event ...

  10. Servlet学习笔记(二)之Servlet路径映射配置、Servlet接口、ServletConfig、ServletContext

    Servlet路径映射配置 要使Servlet对象正常的运行,需要进行适当的配置,以告诉Web容器哪个请求调用哪个Servlet对象处理,对Servlet起到一个注册的作用.Servlet的配置信息包 ...