Handler机制原理解析(二)prepare,loop,post

上一篇已经介绍了Handler机制的原理,如果不熟悉可以看Handler机制原理解析(一)。这一篇,介绍下Handler周边的知识点。我们已经知道,要获得looper对象,必须要先执行prepare。

1,Looper.prepare

    public static void prepare() {prepare(true);}private static void prepare(boolean quitAllowed) {if (sThreadLocal.get() != null) {throw new RuntimeException("Only one Looper may be created per thread");}sThreadLocal.set(new Looper(quitAllowed));}/*** Initialize the current thread as a looper, marking it as an* application's main looper. The main looper for your application* is created by the Android environment, so you should never need* to call this function yourself.  See also: {@link #prepare()}*/public static void prepareMainLooper() {prepare(false);synchronized (Looper.class) {if (sMainLooper != null) {throw new IllegalStateException("The main Looper has already been prepared.");}sMainLooper = myLooper();}}

从prepareMainLooper的注释我们能看到,初始化当前线程为looper,并且标记为应用的主looper,这个主looper是Android帮忙创建的,所有不需要手动调用。我们跟踪这个方法。在ActivityThread中我们看到

public static void main(String[] args) {....Looper.prepareMainLooper();....Looper.loop();....
}

这里我们只需知道,这个方法会在创建应用的时候调用,并且在主Activity的onCreate前已经调用了即可。至于Activity的启动流程,这里不做详述。这里我们同时也看到了另外一个方法,loop。需要注意的是,如果想在工作线程使用Handler,需要手动调用这两个方法,至于顺序,相信你一定知道。

2,post(Runnable)

    public final boolean post(Runnable r){return  sendMessageDelayed(getPostMessage(r), 0);}

只有这一句,接着看吧,先看getPostMessage

    private static Message getPostMessage(Runnable r) {Message m = Message.obtain();m.callback = r;return m;}

这里将Runnable对象r封装进Message对象了。后面就不用再分析了,因为现在已经变成了send(message),前面我们说过,最终都会调用到一个方法上。发送是相同的,可是处理是不同的。还是贴一下处理的代码吧

    public void dispatchMessage(Message msg) {if (msg.callback != null) {handleCallback(msg);} else {if (mCallback != null) {if (mCallback.handleMessage(msg)) {return;}}handleMessage(msg);}}

如果是发送的runnable,则会走第一个分支

    private static void handleCallback(Message message) {message.callback.run();}

这里也没啥,就是让其run起来。再回顾一下,无论在哪个线程post一个Runnable,最终都是会通过dispatch方法,让其run起来,而我们知道,dispatch方法是在主线程。那么View的post方法呢,应该也是封装了Handler的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;}

先看第一个分支,如果有attachinfo,就通过handler post出去。这个应该跟handler的方法一样。

        /*** A Handler supplied by a view's {@link android.view.ViewRootImpl}. This* handler can be used to pump events in the UI events queue.*/final Handler mHandler;

看一下Handler,果然一样。这种是view已经attach到window上了,如果没有呢?看另一个分支

    public void post(Runnable action) {postDelayed(action, 0);}public void postDelayed(Runnable action, long delayMillis) {final HandlerAction handlerAction = new HandlerAction(action, delayMillis);synchronized (this) {if (mActions == null) {mActions = new HandlerAction[4];}mActions = GrowingArrayUtils.append(mActions, mCount, handlerAction);mCount++;}}

这里还是不清楚,继续往下看

    public static <T> T[] append(T[] array, int currentSize, T element) {assert currentSize <= array.length;if (currentSize + 1 > array.length) {@SuppressWarnings("unchecked")T[] newArray = ArrayUtils.newUnpaddedArray((Class<T>) array.getClass().getComponentType(), growSize(currentSize));System.arraycopy(array, 0, newArray, 0, currentSize);array = newArray;}array[currentSize] = element;return array;}

这里能看明白,就是把handlerAction加入到数组中了(Runnable封装在handlerAction中)。这似乎也没得到执行啊。确实

,没办法,既然有post方法,我们姑且尝试看看有没有handle什么之类名字的方法吧。

    public void executeActions(Handler handler) {synchronized (this) {final HandlerAction[] actions = mActions;for (int i = 0, count = mCount; i < count; i++) {final HandlerAction handlerAction = actions[i];handler.postDelayed(handlerAction.action, handlerAction.delay);}mActions = null;mCount = 0;}}

果不其然,能executeAction,并且通过handler post出去了,猜测应该没问题,那就往上找找看吧。在View的dispatchAttachedToWindow中调用的

        if (mRunQueue != null) {mRunQueue.executeActions(info.mHandler);mRunQueue = null;}

哦,原来当view被attach到window上时,就可以通过handler post出去了。其实呢,跟View post方法的第一个分支一样,只不过保证view一定要执行过attach。

Handler机制原理解析(二)prepare,loop,post相关推荐

  1. Handler机制原理解析(一)

    Handler机制原理解析(一) 我们都知道,在Android中,主线程也叫UI线程是负责界面更新的,子线程或者工作线程适合做网络请求,数据库等耗时操作.如果在主线程中执行耗时操作可能引发ANR异常. ...

  2. android Handler机制原理解析(一篇就够,包你形象而深刻)

    首先,我将Handler相关的原理机制形象的描述为以下情景: Handler:快递员(属于某个快递公司的职员) Message:包裹(可以放置很多东西的箱子) MessageQueue:快递分拣中心( ...

  3. AsyncTask机制原理解析

    AsyncTask机制原理解析 Android为我们提供了2种方便的异步处理方案,Handler和AsyncTask,两种方式适合的场景网上一搜就知道了,但是为什么呢?这篇分析将为你揭晓答案.前面分析 ...

  4. Binder通信机制原理解析

    Binder是什么?Binder有啥用?作为一个应用开发者,如果我们开发的应用不涉及跨进程通信(IPC),我想我们也不会去接触Binder.但不知你有没有发现,近来的Andorid面试,都会问及And ...

  5. OkHttp原理解析(二)

    前言 上一篇我们学习了OKHttp的请求执行流程,知道了最终请求流程都会交给getResponseWithInterceptorChain方法来执行,接下来我们就详细分析执行getResponseWi ...

  6. python解析原理_Python语法垃圾回收机制原理解析

    一 引入 解释器在执行到定义变量的语法时,会申请内存空间来存放变量的值,而内存的容量是有限的,这就涉及到变量值所占用内存空间的回收问题,当一个变量值没有用了(简称垃圾)就应该将其占用的内存给回收掉,那 ...

  7. Android实战开发Handler机制深度解析

    本文为自己多年来在Android实战开发过程中总结归纳的一些常见问题,现在分享出来希望对初学者有所帮助. 本文出自门心叼龙的博客,转载请注明出处: https://blog.csdn.net/gedu ...

  8. RCU锁机制原理解析

    背景 为了保护共享数据,需要一些同步机制,如自旋锁(spinlock),读写锁(rwlock),它们使用起来非常简单,而且是一种很有效的同步机制,在UNIX系统和Linux系统中得到了广泛的使用.但是 ...

  9. Hadoop的HA机制原理解析,与HA高可用集群环境搭建

    2019独角兽企业重金招聘Python工程师标准>>> Hadoop的HA工作机制示意图 下面我们开始搭建这一套高可用集群环境 hadoop2.0已经发布了稳定版本了,增加了很多特性 ...

最新文章

  1. 用c++写一个猜数字的小游戏
  2. STM32开发 -- 复位类型判断
  3. ITK:用高斯核计算平滑
  4. bzoj1556 (DP)
  5. spring3: AOP 之 6.2 AOP的HelloWorld
  6. 谈谈 SAP 系统的权限管控和事务记录功能的实现
  7. java+webrtc+回声消除,WebRTC回声消除(2)
  8. opencv+映美相机,从缓冲区中抓图片或者显示视频
  9. 版本控制软件 perforce 与 git
  10. python让solidworks自动建模_让机器学习自动帮我们建模,这4个Python库能让你大开眼界...
  11. Postgres-XL集群的搭建和测试详解
  12. RGB Triplets(后缀和)
  13. python f检验 模型拟合度_python 线性回归分析模型检验标准--拟合优度详解
  14. PowerMockito Mock私有方法
  15. 如何在Mercurial中编辑错误的提交消息? [重复]
  16. 一键如何完成多张静态图合成GIF图?
  17. 【安卓-tio】安卓集成t-io
  18. linux systat安装包,Linux下sysstat 安装
  19. promentheus的组件有_四级考试写作:书信类话题范文模板
  20. linux运维-dovecot+postfix和空壳邮件

热门文章

  1. DVWA关卡3:Cross Site Request Forgery (CSRF)(跨站请求伪造)
  2. 数据结构-顺序表基本操作(C语言实现)
  3. SQL developer 4运行ASH
  4. Linux初学者学习方法
  5. IAR的一个编译错误Error[e27]: Entry GenericApp_Init::?relay in module Coordinator
  6. 4.思科路由器基本配置及排除题目练习
  7. OpenCV 图像轮廓检测
  8. 穷举算法(鸡兔同笼问题)
  9. Python while循环
  10. 0731-并查集-HDU2473