Android消息机制(一) Handler源码阅读

475 阅读3分钟

什么是Handler

  • Handler允许您发送和处理与线程MessageQueue关联的MessageRunnable对象,每个Handler的实例都与一个线程的MessageQueue相关联,当你创建一个新的Handler时,它将被绑定到创建它的线程的MessageQueue,从绑定时起它可以将Message和Runnable对象传递给该MessageQueue并在需要执行这些Message或Runnable时处理这些消息。

Handler 的作用

Handler有两个主要用途:

  • 用来指定Message和Runnable将要执行的时间点(例如延迟几秒后执行)
  • 用来将其它线程要求此线程执行的消息放入MessageQueue中并在需要的时候执行(线程间通讯)

Handler源码解析

  • Handler运行过程中主要对象有两个,一个MessageQueue(消息队列),另一个Looper(消息循环),前者作用是存储handler将要处理的消息,后者则是在MessageQueue有消息时取出交给Handler处理。

    Looper与MessageQueue初始化

    • 首先我们来看LooperMessageQueue来源:handler有7个构造函数,但我们只需要看其中两个主要的构造函数:
 public Handler(Callback callback, boolean async) {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }

        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }
 /**
 * callback:handler处理函数的回调
 * async:是否为异步消息
 **/
 public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

以上展示的是Handler的两个主要构造函数,在其中我们看到mLooper的初始化,一个是通过Looper.myLooper获取Looper实例,另一个通过参数的方式传递进来。

  • Looper.myLooper作用是获取当前线程的Looper实例,当Looper为空时会抛出 Looper.prepare()未调用 异常,因此在子线程中创建Handler有两种方法(主线程在初始化时已经自动调用过Looper.prepare()方法,所以主线程没有手动创建Looper时不会报错)

    • 调用第二个构造函数传入Looper实例;
    • 调用第一个构造函数之前调用Looper.perpare() 创建Looper实例。 注意:若是想要handler正常工作则还需在创建handler之后调用Looper.loop();
  • MessageQueue的初始化则是调用looper.mQueue(),Looper中的MessageQueue则会在调用Looper.perpare时初始。

Handler消息调度

  • Handler可以通过以下7个方法发送消息:

    • post(Runnable)
    • postAtTime(Runnable,long)
    • postDelayed(Runnable,long)
    • sendEmptyMessage(int)
    • sendMessage(Message)
    • sendMessageAtTime(Message,long)
    • sendMessageDelayed(Message,long)
  • 上述7个方法其实最终都会调用下述方法

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

上述方法首先会将handler自身赋值给Message中的target变量,判断是否为异步消(异步消息不受同步屏障影响),最后会调用MessageQueue的enqueue(Message,long)将Message放入消息队列中,至此handler中的消息发送完成。

Handler消息处理

  • Looper.loop方法中会不停在MessageQueue中取出消息,同时会通过Message.target调用Handler的dispatchMessage(Message)方法,将此条消息交给Handler处理
     /**
     * Handle system messages here.
     */
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

此方法首先会判断Message中CallBack是否不为空,通过此判断当前接收的是Message还是Runnable消息,若是Runnable则会调用runnable的run方法,若不是则会先判断CallBack是否为空,若为空则直接调用Handler的handleMessage方法处理消息,若不为空则会调用CallBack的handleMessage处理消息,并通过返回值判断是否继续调用Handler的handlerMessage继续处理消息,至此Handler的消息处理流程完成。

总结

  • 通过上述流程我们可以看出不管Handler是发送消息,还是接收使用的MessageQueue都是同一个,因此在不同线程通过handler发送的消息都是保存在同一份内存中,而Looper.loop()方法则会在创建Handler的线程中通过调用Handler的dispatchMessage分发消息给Handler处理,以此实现了跨线程的传递。

Looper源码