zoukankan      html  css  js  c++  java
  • Android 消息处理源代码分析(1)

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


    在Android中,通常被使用的消息队列的代码在文件夹sourcesandroid-22androidos下,涉及到下面几个类文件
    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;
        }
       
        
    
    
    
    
    
    
    
    
    
    
    
    


  • 相关阅读:
    C++右值引用的参考
    U3D 文档 GPU INSTANCING
    UNITY statistic中的 SetPass和Batches
    时间复杂度
    转,数组遍历的三种方式
    bug纪录:PhotonServer-14052: 17:14:09.033
    关于.net standard 与 .net core, net framework
    【转】未能加载文件或程序集或它的某一个依赖项,系统找不到指定的文件
    C# 计时函数精度测试
    一张图看懂dex
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5239371.html
Copyright © 2011-2022 走看看