Handler机制

来源:互联网 发布:英雄联盟 kda 软件 编辑:程序博客网 时间:2024/06/05 07:35

一、handler中用到的一些类。

1. Message

     消息,理解为线程间通讯的数据单元。例如后台线程在处理数据完毕后需要更新UI,则可发送一条包含更新信息的Message给UI线程。

    2. Message Queue

     消息队列,用来存放通过Handler发布的消息,按照先进先出执行。

    3. Handler

     Handler是Message的主要处理者,负责将Message添加到消息队列以及对消息队列中的Message进行处理。

    4. Looper

     循环器,扮演Message Queue和Handler之间桥梁的角色,循环取出Message Queue里面的Message,并交付给相应的Handler进行处理。

    5. 线程

     UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。

每一个线程里可含有一个Looper对象以及一个MessageQueue数据结构。在你的应用程序里,可以定义Handler的子类别来接收Looper所送出的消息。

二、Handler的用法:

1:传递message。用于接收子线程发送的数据,并用配合主线程更新UI。它有如下方法:

sendEmptyMessage(int what);//发送一个空的消息

sendMessage(Message msg);//发送msg

sendMessageAtTime(Message msg,long uptimeMillis);//在指定时间发送msg

sendMessageDelayed(Message msg,long delayMills);//延迟delatMills秒后发送msg

以上方法最终的调用 其实调用sendMessageAtTime这个方法

2.传递RUnnable对象。通过Handler绑定消息队列,主要有以下方法:

post(Runnable r);

postAtTime(Runnable r,long uptimeMillis);

postDelated(Runnable r,long delayMills);

post一类的方法,允许你排列一个Runnable对象到主线程队列中。所以直接在其run方法中更新UI也是没问题的,因为它处于主线程的队列中。

以上方法其实最终还是调用了 1中的sendMessageAtTime方法;

关于sendMessageAtTime方法,它的源码如下:

public boolean sendMessageAtTime(Message msg, long uptimeMillis) {    MessageQueue queue = mQueue;    if (queue == null) {        RuntimeException e = new RuntimeException(                this + " sendMessageAtTime() called with no mQueue");        Log.w("Looper", e.getMessage(), e);        return false;    }    return enqueueMessage(queue, msg, uptimeMillis);}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {    msg.target = this;    if (mAsynchronous) {        msg.setAsynchronous(true);    }    return queue.enqueueMessage(msg, uptimeMillis);}
queue.enqueueMessage方法的主要操作其实就是向MessageQueue中插入一条数据(注意:MessageQueue虽然翻译过来是消息队列,但是它的内部存储结构并不是真正的队列,而是采用单链表的数据结构来存储消息列表)也就是说Handler发送消息的过程仅仅是向MessageQueue中插入了一条消息,MessageQueue的next方法就会返回这条消息给Looper,Looper收到消息后就开始处理了,最终消息由Looper交由Handler处理,即Handler的dispatchMessage方法会被调用。

3.传递Callback对象。

三、Handler原理

Handler封装了消息的发送(主要包括消息发送给谁)

Looper:

(a).内部包含了一个消息队列MessageQueue,所有Handler发送的消息都走向这个队列。

(b).Looper.loop()方法会一直从MessageQueue取消息,如果有就会通知对应的Handler,调用dispatchMessage(Message msg)方法;而dispatchMessage方法又会调用handlerMessage方法,从而通知handler消息来了。

下面是部分源码:

public static void loop() {    final Looper me = myLooper();    if (me == null) {        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");    }    final MessageQueue queue = me.mQueue;...    for (;;) {        Message msg = queue.next(); // might block        if (msg == null) {            // No message indicates that the message queue is quitting.            return;        }...        try {            msg.target.dispatchMessage(msg);        } finally {            if (traceTag != 0) {                Trace.traceEnd(traceTag);            }        }
...    }}

public void dispatchMessage(Message msg) {    if (msg.callback != null) {        handleCallback(msg);    } else {        if (mCallback != null) {            if (mCallback.handleMessage(msg)) {                return;            }        }        handleMessage(msg);    }}
从源码中也可以看到,loop方法会先通过myLooper方法获取prepare()方法中存放进去的Looper对象,并且得到当前looper下的消息队列。然后一直调用queue.next方法获取消息,当有消息后通过dispatchMessage方法回调hendleMessage方法通知当前handler。

1 0