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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • SSH服务器拒绝密码,再试一次;PermitRootLogin yes无效问题

    SSH服务器拒绝密码,再试一次;PermitRootLogin yes无效问题最近有小伙伴xshell远程登录时,出现了如下情况:网上找的答案也是千篇一律,大多数都是说将PermitRootLogin设置为yes,重启即可,然而很多并不行。在这里,说一下所有解决办法吧,总有一个适合你:如果没有安装ssh,即看不见PermitRootLogin,则使用如下语句安装:sudoapt-getinstallopenssh-server使用vim/etc/s…

    2022年6月11日
    30
  • java spel_SPEL表达式注入-入门篇

    java spel_SPEL表达式注入-入门篇SpringExpressionLanguage(简称SpEL)是一种强大的表达式语言,支持在运行时查询和操作对象图。语言语法类似于UnifiedEL,但提供了额外的功能,特别是方法调用和基本的字符串模板功能。同时因为SpEL是以API接口的形式创建的,所以允许将其集成到其他应用程序和框架中。个人理解就是Spring框架中的一种语言表达式,类似于Struts2中的OGNL的东西。一个最基础的…

    2025年10月29日
    3
  • 第一次安装android studio时候弹出unable to access android sdk add-on list解决方法

    第一次安装android studio时候弹出unable to access android sdk add-on list解决方法

    2021年9月30日
    68
  • SpringBoot防止大量请求攻击

    SpringBoot防止大量请求攻击我们使用Jmeter测试同学的网站时,就会出现网站无法访问,403等错误。Anerroroccurred.Sorry,thepageyouarelookingforiscurrentlyunavailable.Pleasetryagainlater.Ifyouarethesystemadministratorofthisresourcethenyoushouldchecktheerrorlogfordetails.Faithfull

    2022年7月20日
    23
  • js中的prototype的解析

    js中的prototype的解析js的方法可以分为三种:对象方法、类方法、prototype方法//对象方法functionPeople(name){this.name=name;this.introduct=function(){alert(“Mynameis”+this.name);console.log(“Mynameis”+this.name);}}//类方法Peop

    2022年7月23日
    7
  • 此工作站和主域间的信任失败原因_电脑域改为工作组后无法登录

    此工作站和主域间的信任失败原因_电脑域改为工作组后无法登录Thedirectoryserverfailedtoautomaticallyupdateserviceaccount,dnsnameand/orportinformation.这个错误通常是由于访问的主机不能再确保可以和当前加入的活动目录域进行安全通信造成的。当前主机的私有安全凭据和域控制器中的值不匹配。当然简单的可以把安全凭据理解为密码,实际上你知道域环境通过非常严格Kerberos验证,因此实际是Kerberos的Keytable的加密存储在本地安全授权子系统中;

    2022年10月19日
    3

发表回复

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

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