zoukankan      html  css  js  c++  java
  • Handler 源码分析

    Handler用法:

    无参 Handler 构造函数实例化一个 Handler 类型的全局变量,并重写其 handleMessage 方法,在某一方法内调用 Handler 的 sendEmptyMessage 或者sendMessage 发送消息,在某一时刻 handleMessage 回调方法会被调用 。

    Handler 内部定义的两个 final 对象

    final MessageQueue mQueue ;
    
    final Looper mLooper ;

    MessageQueue 即为其内部的消息队列, mQueue 是通过 Looper 的静态变量 mQueue 直接赋值的。而 mLooper是通过 Looper 的静态方法 myLooper() 赋值。

    Looper.myLooper() 实质上调用了 sThreadLocal.get() 来获取与当前线程相关联的 Looper ,源码里面有这样一句话

     // sThreadLocal.get() will return null unless you've called prepare().

    ,在调用该方法之前必须先调用 prepare() 方法,否则该方法返回 null 。但事实上我们并没有调用这个方法,却能成功,原因是为什么呢?

    Looper 内部提供了一个静态方法 prepareMainLooper ,这个方法是在应用程序创建的时候直接由 android 系统调用的。

    /** 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 Androidenvironment,
    
         *  so you should never need to call this function yourself.
    
    */

    该方法调用了 prepare () 方法和 setMainLooper (myLooper ()) 并将 myLooper () 返回的值设置为主线程的 looper 。

    接下来看 sendEmptyMessage 和其他几个发送消息的方法,它们最终都会调用到 sendMessageAtTime 这样一个方法,而这个方法会调用 MessageQueue 提供的 enqueueMessage 方法,该方法将发送的消息放入消息队列里面,最后调用

    nativeWake(mPtr) 方法,这是一个 C++ 实现的方法,具体的实现内容没有深究,但应该间接调用到 Looper loop() 方法。

    接下来看一下 loop() 方法,这个方法从消息队列中取出消息,然后调用里面存放的 target 的 dispatchMessage 方法:

    msg.target.dispatchMessage(msg);

    msg.target 存放的是在构造消息的类的 handler 对象,事实上这里回调了 handler 的 dispatchMessage 方法,该方法会调用 handleMessage 方法。

  • 相关阅读:
    【Leetcode周赛】从contest-81开始。(一般是10个contest写一篇文章)
    【LeetCode】抽样 sampling(共4题)
    【LeetCode】拓扑排序 topological-sort(共5题)
    【LeetCode】几何学 geometry(共2题)
    【读书笔记】C/C++程序员面试秘籍
    【读书笔记】程序员面试笔记
    【sql】牛客网练习题 (共 61 题)
    HDU 6119 小小粉丝度度熊 双指针
    2017多校第7场 HDU 6128 Inverse of sum 推公式或者二次剩余
    2017多校第7场 HDU 6121 Build a tree K叉树,思维
  • 原文地址:https://www.cnblogs.com/xinmengwuheng/p/5792488.html
Copyright © 2011-2022 走看看