Android 消息处理机制源码详细分析教程

Android中被使用的消息队列的代码在目录\sources\android-22\android\os下,主要涉及到以下几个类文件

Handler.java  在这里面代表一个消息实体对象
Looper.java  主要用来监听MessageQueue的消息,他存放于ThreadLocal中
Message.java  主要用来处理消息的发送,以及响应消息的业务处理
MessageQueue.java  是一个单独的线程,可与Looper整合,实现一个完全独立的消息处理机制

Message.java  
public final class Message implements Parcelable {  
  
    public int what;    //消息种类  
  
    public int arg1;    //低开销的整型参数  
  
    public int arg2;  
  
    public Object obj;  //Object型数据  
  
    public Messenger replyTo;  //消息处理完后通知给发送者  
  
    /*package*/ int flags;   //消息标记:正在使用和异步等  
  
    /*package*/ long when;   //消息创建时的时间  
      
    /*package*/ Bundle data; //消息附带的额外数据  
      
    /*package*/ Handler target; //消息接受者,处理者  
      
    /*package*/ Runnable callback; //优先使用回调处理来处理消息  
      
    /*package*/ Message next;   //下一个消息,形成链表  
  
    private static Message sPool;    //消息池中的头消息

          
      
上面中的target,通常由重新实现的Handler子类的handleMessage函数来处理消息  
 

 public static Message obtain() {     //获取消息的函数,如果有消息的话则获取出来m,链表指针移动一位,否则则返回一条空消息  
        synchronized (sPoolSync) {  
            if (sPool != null) {  
                Message m = sPool;  
                sPool = m.next;  
                m.next = null;  
                m.flags = 0; // clear in-use flag  
                sPoolSize--;  
                return m;  
            }  
        }  
        return new Message();  
    }  
  
  
 public void sendToTarget() {    //发送消息给处理者  
        target.sendMessage(this);    //调用Handler.java中的函数  
    }  
  
}
MessageQueue.java  
public final class MessageQueue {  
      
    Message mMessages;    //当前要处理的消息  
      
    //当需要从链表中获取一个消息时,就会调用next函数,若消息队列中没有消息,则会阻塞等待,通过调用nativePollOnce函数来完成  
    Message next() {...}  
      
    boolean enqueueMessage(Message msg, long when) {     //按时间顺序添加消息  
        if (msg.target == null) {  
            throw new IllegalArgumentException("Message must have a target.");  
        }  
        if (msg.isInUse()) {  
            throw new IllegalStateException(msg + " This message is already in use.");  
        }  
  
        synchronized (this) {  
            if (mQuitting) {  
                IllegalStateException e = new IllegalStateException(  
                        msg.target + " sending message to a Handler on a dead thread");  
                Log.w("MessageQueue", e.getMessage(), e);  
                msg.recycle();  
                return false;  
            }  
  
            msg.markInUse();  
            msg.when = when;  
            Message p = mMessages;  
            boolean needWake;  
            if (p == null || when == 0 || when < p.when) {  
                // New head, wake up the event queue if blocked.  
                msg.next = p;  
                mMessages = msg;  
                needWake = mBlocked;  
            } else {  
                // Inserted within the middle of the queue.  Usually we don't have to wake  
                // up the event queue unless there is a barrier at the head of the queue  
                // and the message is the earliest asynchronous message in the queue.  
                needWake = mBlocked && p.target == null && msg.isAsynchronous();  
                Message prev;  
                for (;;) {  
                    prev = p;  
                    p = p.next;  
                    if (p == null || when < p.when) {  
                        break;  
                    }  
                    if (needWake && p.isAsynchronous()) {  
                        needWake = false;  
                    }  
                }  
                msg.next = p; // invariant: p == prev.next  
                prev.next = msg;  
            }  
  
            // We can assume mPtr != 0 because mQuitting is false.  
            if (needWake) {        
                nativeWake(mPtr);  //调用底层唤醒函数,管道唤醒  
            }  
        }  
        return true;  
    }
Looper.java
public final class Looper {
    final MessageQueue mQueue;   //消息队列
    final Thread mThread;   //Looper联系的线程
    
    public static void prepare() {
        prepare(true);
    }
    
    private static void prepare(boolean quitAllowed) {   //先会检查是否有Looper,若有则抛出异常,没有的话则创建一个Looper实例保存起来
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }
   //在这个线程中运行消息队列,调用quit()停止
   public static void loop() {
    ...
    final MessageQueue queue = me.mQueue;
        // Make sure the identity of this thread is that of the local process,
        // and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();
        for (;;) {
            Message msg = queue.next(); // 从消息队列中取出一条消息
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            // This must be in a local variable, in case a UI event sets the logger
            Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }
            msg.target.dispatchMessage(msg);   //交给msg的handler分发消息处理
    ...
   }
    //取出当前线程的Looper,返回空则表示当前线程没有Looper
    public static Looper myLooper() {
        return sThreadLocal.get();
    }
}
Handler.java
public class Handler {
     //定义Callback接口
     public interface Callback {
          public boolean handleMessage(Message msg);
     }
    
     //子类要实现的消息处理方法
     public void handleMessage(Message msg) {
     }
     * Handle system messages here.
     */
    public void dispatchMessage(Message msg) {        //分发信息
        if (msg.callback != null) {          //若指定了msg.callback,则由它处理
            handleCallback(msg);
        } else {
            if (mCallback != null) {        //若指定了Handler.mCallback,则由它处理
                if (mCallback.handleMessage(msg)) {    //调用mCallback接口的实现方法
                    return;
                }
            }
            handleMessage(msg);   最后才调用Handler自身重载的handleMessage方法
        }
    }
    分发消息函数中,消息先会检查自身有没有处理自身的回调Runnable,若有则由它处理,若没有则会检查该handler有无自身的回调处理,若有则调用,若没有则调用自身重载的handleMessage方法
    //Handler的生成总是和它当前所处线程有关的,如果当前线程中没有一个Looper,则会报错,UI线程中默认有产生Looper的函数
    public Handler() {
        this(null, false);
    }    
    //使用指定的Looper(可以处理那个Looper线程中的消息),不用默认的从当前线程中取出Looper
    public Handler(Looper looper) {
        this(looper, null, false);
    }
   ...
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索int
, 函数
, new
, null
, synchronized
消息队列
android 消息推送机制、android消息处理机制、android 消息机制、android消息传递机制、android消息分发机制,以便于您获取更多的相关知识。

时间: 2024-09-24 18:59:05

Android 消息处理机制源码详细分析教程的相关文章

Android入门之源码开发基础教程_Android

本文讲述了Android入门之源码开发基础教程.分享给大家供大家参考,具体如下: 下载 Android 源码之后,接下来就是学习或者进行开发. 在开发之前,谈一些开发必备知识或者工具,工欲善其事必先利其器嘛! 在前面一篇<Android入门之使用eclipse进行源码开发的方法>中基本上说了开发使用工具. 但是我们如何使用模拟器开发呢?! 当然你去删除或者增加app到模拟器就不可以按常规来操作了,花 5 -10 分钟了解一下,如果你有需要. 0. 编译源码 直接在下载的源码根目录下面,执行:

Android入门之源码开发基础教程

本文讲述了Android入门之源码开发基础教程.分享给大家供大家参考,具体如下: 下载 Android 源码之后,接下来就是学习或者进行开发. 在开发之前,谈一些开发必备知识或者工具,工欲善其事必先利其器嘛! 在前面一篇<Android入门之使用eclipse进行源码开发的方法>中基本上说了开发使用工具. 但是我们如何使用模拟器开发呢?! 当然你去删除或者增加app到模拟器就不可以按常规来操作了,花 5 -10 分钟了解一下,如果你有需要. 0. 编译源码 直接在下载的源码根目录下面,执行:

Java的HashMap源码实现分析教程

1.简介 通过上面的一篇随笔我们知道了HashSet的底层是采用Map实现的,那么Map是什么?它的底层又是如何实现的呢?这下我们来分析下源码,看看具体的结构与实现.Map 集合类用于存储元素对(称作"键"和"值"),其中每个键映射到一个值.Map.Entry是其的内部类,描述Map中的按键/数值对.需要指出的是 Map,允许null的键也允许null的值.它的实现主要有HashMap和sortedMap,其中SortedMap扩展了Map使按键保持升序排列,下面我

Thrift的代码生成器Compiler原理及源码详细解析 1 类关系图

最近忙着研究GlusterFS,本来周末打算写几篇博客的,但是由于调试GlusterFS的一些新增功能就 用了整整的一天,还有一天就陪老婆大人逛街去了!今晚浏览完微博发现时间还早就来博客一篇,本篇 博客内容主要是前一段时间研究的Thrift的代码生成器的源码详细分析,没有具体分析语法解析,因为 是工具字段生成的代码,人是没有办法阅读的----到处都是跳转表!由于Thrift支持N多种语言,但是 生成代码原理都差不多,我主要分析了C++相关代码生成.关于Thrift的使用及原理.代码网上基本上 都

Android Handler消息派发机制源码分析_Android

注:这里只是说一下sendmessage的一个过程,post就类似的 如果我们需要发送消息,会调用sendMessage方法 public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } 这个方法会调用如下的这个方法  public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMill

自定义View系列教程02--onMeasure源码详尽分析

探索Android软键盘的疑难杂症 深入探讨Android异步精髓Handler 详解Android主流框架不可或缺的基石 站在源码的肩膀上全解Scroller工作机制 站在源码的肩膀上全解Scroller工作机制 Android多分辨率适配框架(1)- 核心基础 Android多分辨率适配框架(2)- 原理剖析 Android多分辨率适配框架(3)- 使用指南 自定义View系列教程00–推翻自己和过往,重学自定义View 自定义View系列教程01–常用工具介绍 自定义View系列教程02–

自定义View系列教程03--onLayout源码详尽分析

探索Android软键盘的疑难杂症 深入探讨Android异步精髓Handler 详解Android主流框架不可或缺的基石 站在源码的肩膀上全解Scroller工作机制 Android多分辨率适配框架(1)- 核心基础 Android多分辨率适配框架(2)- 原理剖析 Android多分辨率适配框架(3)- 使用指南 自定义View系列教程00–推翻自己和过往,重学自定义View 自定义View系列教程01–常用工具介绍 自定义View系列教程02–onMeasure源码详尽分析 自定义View

Android消息循环机制源码深入理解

Android消息循环机制源码 前言: 搞Android的不懂Handler消息循环机制,都不好意思说自己是Android工程师.面试的时候一般也都会问这个知识点,但是我相信大多数码农肯定是没有看过相关源码的,顶多也就是网上搜搜,看看别人的文章介绍.学姐不想把那个万能的关系图拿出来讨论. 近来找了一些关于android线程间通信的资料,整理学习了一下,并制作了一个简单的例子. andriod提供了 Handler 和 Looper 来满足线程间的通信.例如一个子线程从网络上下载了一副图片,当它下

android微信支付源码分享_Android

本文为大家分享了android微信支付源码,供大家参考,具体内容如下 参数配置 public static final String APP_ID ; /** 在微信开放平台注册app,微信给分配的id **/ public static final String MCH_ID; /** 申请开通微信支付,成功后微信会给你发一封邮件,给你分配一个商户平台账号,在资料里有商户ID **/ public static final String API_KEY; /** 在微信发给你的那封邮件里,给你