Android Handler运行机制

作者: LeaYw | 来源:发表于2017-01-19 18:17 被阅读132次

    Handler 的作用

    There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.
    简单来说就是消息调度和线程切换。

    发送消息

    子线程中使用 Handler 通知主线程更新 UI 有下列几种方式

    • post(Runnable r)
    • postAtTime(Runnable r, long uptimeMillis)
    • postAtTime(Runnable r, Object token, long uptimeMillis)
    • postDelayed(Runnable r, long delayMillis)
    • postAtFrontOfQueue(Runnable r)
    • sendMessage(Message msg)
    • sendEmptyMessage(int what)
    • sendEmptyMessageDelayed(int what, long delayMillis)
    • sendEmptyMessageAtTime(int what, long uptimeMillis)
    • sendMessageDelayed(Message msg, long delayMillis)

    最后都会通过 sendMessageAtTime(Message msg, long uptimeMillis) 或 sendMessageAtFrontOfQueue(Message msg) 方法调用 enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) 将 Message 传入 MessageQueue 的 enqueueMessage(msg, uptimeMillis) 方法,从而将 msg 加入消息队列中。
    这里看一下 Handler 的 enqueueMessage 方法

    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
            msg.target = this;//注意这里会把handler存到msg中
            if (mAsynchronous) {
                msg.setAsynchronous(true);
            }
            return queue.enqueueMessage(msg, uptimeMillis);
        }
    
    

    消息传递

    通过 MessageQueue 中的 enqueueMessage 方法会将 message 加入到消息队列,MessageQueue 类中提供了 next() 方法用于从消息队列中取出 msg 。
    创建 Handler 的会检查当前线程中是否有 Looper 对象,没有就会抛 RuntimeException 。如果在非主线程下使用需要自行创建,下面给出官方示例:

    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();
            }
    

    loop 方法中会一直调用 MessageQueue 的 next() 方法检查消息队列中是否有新消息,如果有新消息就会调用msg中存储的 Handler 对象的 dispatchMessage 方法,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);//msg 在enqueueMessage方法中将target赋给msg
                } finally {
                    ...
                }
                msg.recycleUnchecked();
            }
    

    其中 myLooper() 方法会通过 ThreadLocal 返回当前线程中的 Looper 对象。
    这样就讲线程转换成 handler 所在线程,执行 handler 的 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);
            }
        }
    

    在 Android 中使用 Handler 通常有三种方式。

    • 默认构造函数
    Handler handler = new Handler();
    
    • 实现 Handler 中定义的CallBack接口,接口中定义了 HandleMessage 方法。
    Handler handler = new Handler(new Handler.Callback() {
                @Override
                public boolean handleMessage(Message msg) {
                    return false;
                }
            });
    
    • 自定义 Handler 继承 Handler
    static class MyHandler extends Handler{
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
            }
        }
    

    所以 handler 会先处理 msg 中的 CallBack(会在 post 或 send 时将参数里的 Runable 赋给 msg ),然后处理在通过第二种构造方法创建 Handler 时传入的 CallBack ,如果都没有就执行子类实现的 HandleMessage 方法了。
    Handler的运行机制大致到此,一些细节还是需要到源码中探索。

    相关文章

      网友评论

        本文标题:Android Handler运行机制

        本文链接:https://www.haomeiwen.com/subject/slwibttx.html