299_Handler发送消息

来源:互联网 发布:java poi设置高度 编辑:程序博客网 时间:2024/05/24 04:25




Handler发送消息


阅读郭霖大神博客的读书笔记


博客地址:http://blog.csdn.net/sinyu890807/article/details/9991569






一.发送消息
    new Thread(new Runnable() {  
        @Override  
        public void run() {  
            Message message = new Message();  
            message.arg1 = 1;  
            Bundle bundle = new Bundle();  
            bundle.putString("data", "data");  
            message.setData(bundle);  
            handler.sendMessage(message);  
        }  
    }).start();  






二.如何发送,如何接收
先看看sendMessage方法发送消息
除了sendMessageAtFrontOfQueue()方法,其他方法全都会调用sendMessageAtTime()方法
所以看sendMessageAtTime()
    public boolean sendMessageAtTime(Message msg, long uptimeMillis)  
    {  
        boolean sent = false;  
        MessageQueue queue = mQueue;  
        if (queue != null) {  
            msg.target = this;  
            sent = queue.enqueueMessage(msg, uptimeMillis);  
        }  
        else {  
            RuntimeException e = new RuntimeException(  
                this + " sendMessageAtTime() called with no mQueue");  
            Log.w("Looper", e.getMessage(), e);  
        }  
        return sent;  
    }  


传入两个参数,一个message就是我们要发的消息,一个time是发送时间
定义一个boolean值sent为false,
定义一个MessageQueue,把成员变量mQueue赋值给他
如果queue不为空,也就是mQueue不为空
msg.target=this;
sent为queue调用enqueueMessage返回值,也是传入msg和time
返回 sent值


MessageQueue就是一个消息队列,将所有收到的消息以队列的形式进行排列,
并提供入队和出队的方法.
这个类是在Looper的构造函数中创建的,
所以一个Looper也就对应了一个MessageQueue.
所以enqueueMessage也就是入队的方法






三.enqueueMessage方法
    final boolean enqueueMessage(Message msg, long when) {  
        if (msg.when != 0) {  
            throw new AndroidRuntimeException(msg + " This message is already in use.");  
        }  
        if (msg.target == null && !mQuitAllowed) {  
            throw new RuntimeException("Main thread not allowed to quit");  
        }  
        synchronized (this) {  
            if (mQuiting) {  
                RuntimeException e = new RuntimeException(msg.target + " sending message to a Handler on a dead thread");  
                Log.w("MessageQueue", e.getMessage(), e);  
                return false;  
            } else if (msg.target == null) {  
                mQuiting = true;  
            }  
            msg.when = when;  
            Message p = mMessages;  
            if (p == null || when == 0 || when < p.when) {  
                msg.next = p;  
                mMessages = msg;  
                this.notify();  
            } else {  
                Message prev = null;  
                while (p != null && p.when <= when) {  
                    prev = p;  
                    p = p.next;  
                }  
                msg.next = prev.next;  
                prev.next = msg;  
                this.notify();  
            }  
        }  
        return true;  
    }  


传入msg和when,返回boolean
如果msg的when不为0,报错:这个消息已经在使用了
如果msg的target为空而且mQuitAllowed为false
报错:主线程不允许退出
如果mQuiting为true,报错:往死线程的Handler发送了消息
如果target为空,mQuiting为true
然后就是对消息按照时间来排序
具体的操作方法就根据时间的顺序调用msg.next,从而为每一个消息指定它的下一个消息是什么。






四.出队方法Looper.loop()
    public static final void loop() {  
        Looper me = myLooper();  
        MessageQueue queue = me.mQueue;  
        while (true) {  
            Message msg = queue.next(); // might block  
            if (msg != null) {  
                if (msg.target == null) {  
                    return;  
                }  
                if (me.mLogging!= null) me.mLogging.println(  
                        ">>>>> Dispatching to " + msg.target + " "  
                        + msg.callback + ": " + msg.what  
                        );  
                msg.target.dispatchMessage(msg);  
                if (me.mLogging!= null) me.mLogging.println(  
                        "<<<<< Finished to    " + msg.target + " "  
                        + msg.callback);  
                msg.recycle();  
            }  
        }  
    }  
这里有一个死循环,一直调用queue的next方法
next方法就是如果当前MessageQueue中存在mMessages(即待处理消息),就将这个消息出队,然后让下一条消息成为mMessages,否则就进入一个阻塞状态,一直等到有新的消息入队。


msg.target.dispatchMessage(msg); 
每当有一个消息出队,就将它传递到msg.target的dispatchMessage()方法中






五.Handler中dispatchMessage()方法
    public void dispatchMessage(Message msg) {  
        if (msg.callback != null) {  
            handleCallback(msg);  
        } else {  
            if (mCallback != null) {  
                if (mCallback.handleMessage(msg)) {  
                    return;  
                }  
            }  
            handleMessage(msg);  
        }  
    }  
如果mCallback不为空,则调用mCallback的handleMessage()方法,否则直接调用Handler的handleMessage()方法,并将消息对象作为参数传递过去。








六.最标准的异步消息处理线程的写法
    class LooperThread extends Thread {  
          public Handler mHandler;  
      
          public void run() {  
              Looper.prepare();  
      
              mHandler = new Handler() {  
                  public void handleMessage(Message msg) {  
                      // process incoming messages here  
                  }  
              };  
      
              Looper.loop();  
          }  
      }  









0 0
原创粉丝点击