Android之Handler

    Handler:Handler容许你发送而且处理和线程消息队列相关的消息(Message)和可运行对象。每一个Handler实例都有一个单独的相关线程和这个线程的消息队列。当你建立一个新的Handler时候,它将和建立者所在线程以及此线程的消息队列绑定。从这一刻起,它将传递消息和可运行对象到消息队列,并在消息和可运行对象被传出消息队列时执行它们。 java

        Handler主要有两种用途:(1)把要被执行的消息和可运行对象添加到将要执行的任务清单里。(2)把要在另一条线程上执行的动做列入本身的队列。 ide

        安排消息到任务清单,可使用如下几种方法:post,postAtTime(Runnable,long),postDelayed,sendEmptyMessage,sendMessage,sendMessageAtTime以及sendMessageDelayed方法。post版本的方法容许你安排Runnable对象到任务清单,这些Runnable对象将在消息队列接收到后调用它们。sendMessage版本的方法容许你安排一个Message对象到任务清单,这个Message对象包含一个将被Hanlder的handleMessage方法处理的数据包(须要在你的子类中实现handleMessage方法)。 oop

        你在posting或者sending时,既能够容许消息循环在准备完成后当即处理任务,也能够在执行任务以前指定一个延迟时间。上述post和send系列的最后两个方法能够设置超时、空转和定时行为。 post

        当你的应用程序建立一个进程的时候,这个进程的主线程就专门运行一个负责管理顶级程序对象(activities,broadcast receivers等等)和全部由这些对象建立的窗口的消息循环。你能够建立本身的线程,而且经过一个Handler和应用的主线程沟通。这样作跟以前调用post或者sendMessage同样,只不过是在你的子线程中调用的。给定的Runnable对象或者Message将被添加到Hanlder的消息队列,而且在适当的时候处理它们。 ui

        Hanlder默认的构造方法,将这个Handler跟当前线程中的队列关联了起来: this

public Handler() {     mLooper = Looper.myLooper(); if (mLooper == null) {      throw new RuntimeException(             "Can't create handler inside thread that has not called Looper.prepare()");     }     mQueue = mLooper.mQueue;  mCallback = null; }

        Handler必需要有一个消息队列,否则它无法接受消息。在线程初始化Handler以前,必须调用Looper.prepare(),详细内容请参考《Android之Looper》。  spa

        初始化Handler时,还能够指定Looper和Callback,前者可使消息循环在Looper相关的线程中运行,后者可使你避免重写Handler。 .net

        Handler的obtainMessage系列方法都是从全局的消息池中拿Message,若是池中没有,就new一个返回。 线程

        post系列方法,都是封装的对应的send系列方法(将Runnable对象(msg.callback)和一个Object对象(即msg.object,若是有的话)经过getPostMessage方法拿到一个Message,而后send)。 code

private final Message getPostMessage(Runnable r, Object token) {
    Message m = Message.obtain();
    m.obj = token;
    m.callback = r;
    return m;
}

        send系列方法,包装的都是sendMessageAtTime方法(sendMessageAtFrontOfQueue方法也是它的一个变种)。在sendMessageAtTime方法中,第一个参数是将被传递的Message对象,第二个是传递时的时间(能够猜测delayed系列方法都是当前时间加上延迟时间,事实证实这种猜测是正确的)。

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排入消息队列(队列中按照uptimeMillis排序,而sendMessageAtFrontOfQueue方法中将它设为0,因此sendMessageAtFrontOfQueue方法传递的Message将在Looper的loop方法循环的下一次循环中当即执行)。enqueueMessage方法的排序部分以下:

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;
    //Log.d("MessageQueue", "Enqueing: " + msg);
    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();
    }
}

        将Message排入消息队列后的事情,是由Looper来完成的,详见《Android之Looper》中的loop方法。在Looper的loop方法中,调用了msg.target(即Handler,见sendMessageAtTime方法)的dispatchMessage方法。

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

        第一个判断,msg.callback即为post系列方法传递到的Runnable对象。

private final void handleCallback(Message message) {
    message.callback.run();
}

        第二个mCallback.handleMessage方法,可让你避免在本身的Handler子类中重写handleMessage方法。

        还有remove系列方法,就是根据条件从消息队列中移除相关的Message。

相关文章
相关标签/搜索