Android 消息处理源代码分析(1)

Android 消息处理源代码分析(1)

Android 消息处理源代码分析(1)

在Android中,通常被使用的消息队列的代码在文件夹\sources\android-22\android\os下,涉及到下面几个类文件

Handler.java

Looper.java

Message.java

MessageQueue.java

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;
    }
   
    











版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/109131.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Log4j ConversionPattern参数的格式含义[通俗易懂]

    Log4j ConversionPattern参数的格式含义[通俗易懂]ConversionPattern参数的格式含义格式名含义%c输出日志信息所属的类的全名%d输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy-MM-ddHH:mm:ss},输出类似:2002-10-18-22:10:28%f输出日志信息所属的类的类名%l输出日志事件的发生位置,即输出日志信息的语句处于它所在的类的第几

    2022年8月22日
  • php开发在线客服系统_app内在线客服

    php开发在线客服系统_app内在线客服  在本节中,我们将简要讨论通过PHP在线客服系统源码传输数据的数据传输方法。我们可以发送普通消息或基于时间表的消息。我们将逐一介绍这两种基本类型的消息传递。  完整源码:zxkfym.top  Azure服务总线:MicrosoftAzure服务总线是一种完全托管的云上企业集成消息传递服务,用于将云中运行的任何应用程序、设备和服务连接到任何其他应用程序或服务。该平台充当云上和任何设备上的应用程序的消息传递骨干。  它是如何工作的?使用消息在不同的应用程序和服务之间传输数据。消息为二进制格

    2022年9月2日
  • java基础案例4-4学生和老师「建议收藏」

    java基础案例4-4学生和老师「建议收藏」packagecom.itheima;importjava.util.Scanner;abstractclassPerson{voidspeak(){}}classTeacherextendsPerson{privateStringname;voidsetName(Stringname){this.name=name;}StringgetName(){returnname;.

    2022年6月20日
  • 一种Python工具的License授权机制

    一种Python工具的License授权机制作为一种流行语言,在不同的应用领域,利用Python书写的工具越来越多。Python具有应用领域广泛、简单易学、功能强大等特点,但是在很多场合它也具有一些较难克服的缺点:代码明文,较难加密。 由于#1,python脚本很难应用于收费工具领域。那么如果我想对一个Python工具的使用加以限制,有没有什么方法可以实现呢?本文提供一种简易的License授权机制实现思路,它主要包括如下几部分内容:如何生成一个加密的License文件。 如何做License内容核验。…

    2022年11月1日
  • tensor 和 numpy 的互相转换

    tensor 和 numpy 的互相转换为什么要相互转换:1.要对tensor进行操作,需要先启动一个Session,否则,我们无法对一个tensor比如一个tensor常量重新赋值或是做一些判断操作,所以如果将它转化为numpy数组就好处理了。下面一个小程序讲述了将tensor转化为numpy数组,以及又重新还原为tensor:2.Torch的Tensor和numpy的array会共享他们的存储空间,修改一个会导致另外的一…

    2022年10月19日
  • ping命令的使用及代码_通过命令查看ping路径

    ping命令的使用及代码_通过命令查看ping路径在这个时代,科技越来越发达,网络已经越来越成为人们不可缺少的一部分。计算机也已经是很多学校的课程了,因为计算机技术是非常有技术性的专业,它其中涉及到很多专业知识,需要通过学习才能掌握。今日小编就为大家介绍一个计算机的命令,它叫做Ping,这边介绍一下它的入门知识,主要是关于ping连接和命令方面的介绍。  1、Ping的基础知识  ping命令相信大家已经再熟悉不过了,但是能把ping的功能发…

    2022年4月19日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号