Android 之 Handler ,Looper机制详解

Android 之 Handler ,Looper机制详解

Handler 在日常开发中异步操作时经常使用到,接下来我们就来分析Handler机制,主要分为两大部分:

  • 常见用法
  • 源码解读

常见用法

一般我们会在Acticity或者其他地方中new一个Handler ,并重写handleMessage的方法,在handleMessage中接受传过来的消息:

    private Handler mHandler = getLocalHandler();
    private final static int FIRST_MESSAGE = 1;
    private final static int SECOND_MESSAGE = 2;

    public Handler getLocalHandler() {
        Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case FIRST_MESSAGE:
                        //doFirstThing();
                        break;
                    case SECOND_MESSAGE:
                        //doSecondThing();
                        break;
                    default:
                        break;
                }
            }
        };
        return handler;
    }

然后可以在 其他的线程 或者 主线程 发消息给Handler,比如异步网络加载完数据之后:

    private void sendMessageToFirst() {
        Message msg = new Message();
        msg.obj = null;
        //可用 msg.what 来区别并执行不同的事项
        msg.what = FIRST_MESSAGE;
        mHandler.sendEmptyMessage(FIRST_MESSAGE);
    }

在 异步线程 或 主线程 我们也可以利用Handler来做延时处理操作:

    private void sendMessageDelayed() {
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                doSecondThing();
            }
        },2333);
    }

上诉就是我们比较常规的用法。

源码解读篇

接下来我们来分析下Handler,Looper机制的java源码

Handler(初始化):

首先看下new时Handler的构造器,代码如下:

    public Handler() {
        this(null, false);
    }

    public Handler(Callback callback, boolean async) {
        //...
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException("");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

可以看到,new时初始化 mLooper (Looper) ,mQueue (MessageQueue) ,mCallback (Callback) ,mAsynchronous (Boolean) 这四个对象。
下面我们逐一来分析他们:

Callback :

先说Callback,Callback是Handler类中的接口,其中的handleMessage与我们上述Handler重写的handleMessage是一样的方法名:

    public interface Callback {
        public boolean handleMessage(Message msg);
    }

我们直接看他调用的地方,它在dispatchMessage方法中被使用,dispatchMessage(Message msg) 是处理消息的分发的方法,而方法中的 handleMessage(msg) ,它是我们执行 handler中 sendMessage,post(Runnable)等方法的执行语句

    // dispatchMessage方法中被使用,dispatchMessage(Message msg) 
    // 是处理消息的分发的方法

    public void dispatchMessage(Message msg) {
        //..
        // 这个为callback
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        //执行handler中 sendMessage,post等方法的分发执行语句
        handleMessage(msg);
    }

再看下callback调用的地方,可看到当 mCallback != null 且 mCallback.handleMessage(msg) 为 true 的时候 return 方法不继续往下走。不然执行handleMessage(msg),这说明我们在 handler 事件执行前多执行一些操作 或者 截断handler事件的执行,所以可以使用下述的初始化Handler构造器,不过很少使用到这个。

 //Handler.class

 public Handler(Callback callback) {
    this(callback, false);
 }

 Handler handler = new Handler(new Handler.Callback() {
      @Override
      public boolean handleMessage(Message msg) {
           //可以在事件发送前自定义处理
           // doSomeThing();
           return false;
      }
  });

Looper:

接下来我们看下 mLooper 参数,它被赋值了 Looper.myLooper(),我们进Looper进去看,相关代码贴下去:

    static final ThreadLocal sThreadLocal 
         = new ThreadLocal();

    public static Looper myLooper() {
        return sThreadLocal.get();
    }

可以看到是从 sThreadLocal 获取一个Looper,使得且一个线程只有一个Looper,大家可以去网上搜索ThreadLocal的知识理解为什么线程只有一个Looper。在 get 之前肯定需初始化,我们找到初始化的地方,代码如下:

    private static Looper sMainLooper

    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                    throw new IllegalStateException("");
            }
            sMainLooper = myLooper();
        }
    }

    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException(
            "Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

在代码中,我们可以看到新建了一个MessageQueue,我们进去看下:

    MessageQueue(boolean quitAllowed) {
        mQuitAllowed = quitAllowed;
        mPtr = nativeInit();
    }

    void quit(boolean safe) {
        if (!mQuitAllowed) {
                throw new IllegalStateException(
                "Main thread not allowed to quit.");
        }
        // ...
    }

其中quitAllowed代表这个消息队列是否可以停止,上诉可以看到赋值为false时,调用quit()方法会报异常, 而mPtr是被底层c++使用,这个我们先不理。此时初始化已经分析完毕。

Handler机制(启动):

在我们程序启动时,系统会调用 prepareMainLooper() 方法,并初始化主线程的 Looper ,使主线程有可以使用的 Looper(),其中prepareMainLooper() 中 prepare(false) 会使Looper运行起来且不允许MessageQueue消息队列中断,这也可以理解不然在主UI中中断了可就不好了,代码如下:

    // ActivityThread.class 主程序的入口

    public static void main(String[] args) {
        // ..
        Looper.prepareMainLooper();
        // ..
        Looper.loop();
        // ..
    }

在上面可以看到在主程序开始时就就调用了prepareMainLooper()并使Looper loop()了起来,我们看下loop()方法,代码如下 :

 public static void loop() {
        final Looper me = myLooper();
        // ...
        final MessageQueue queue = me.mQueue;
        // ...
        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) { 
                return;
            }
            // ...
            try {
                msg.target.dispatchMessage(msg);
            } finally {
                // ...
            }
            // ...
            msg.recycleUnchecked();
        }
    }

可以看到方法中,获取当前MessageQueue对象,并开启了死循环,当queue.next()消息队列没有消息就return继续等待,有消息的话就往下执行 msg.target.dispatchMessage(msg) 语句。我们去先下queue.next()中的内容,代码如下:

    // MessageQueue.class

    Message next() {
        // 当loop被停止或者弃用 ptr 为0
        final long ptr = mPtr;
        if (ptr == 0) {
            return null;
        }
        //...

        // 下一次消息触发时间
        int nextPollTimeoutMillis = 0;

        for (;;) { 
            //...
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }

            nativePollOnce(ptr, nextPollTimeoutMillis);

            synchronized (this) {
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
                // 如果同步时执行 且 msg.target == null执行
                if (msg != null && msg.target == null) {
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (
                    msg != null && !msg.isAsynchronous());
                }

                if (msg != null) {
                    if (now < msg.when) {
                        nextPollTimeoutMillis 
                        = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    nextPollTimeoutMillis = -1;
                }
                if (mQuitting) {
                    dispose();
                    return null;
                }
            }
            //...
        }
    }

我们可以看到通过next()方法,我们可以获取消息继而执行,接着target是什么,代码如下:

    // Message.class

    Handler target;

可以看到 target 是个Handler对象,之前有稍微讲下Handler的dispatchMessage()方法,让我们再看一遍详细代码:

    // Handler.class

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

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

    public void handleMessage(Message msg) {
    }

可以看到当传下来的消息msg中的callback不为空的时候,直接执行run()方法,不然就判断mCallback 是否为空且mCallback.handleMessage(msg)是否为true,不然就执行我们重写的handleMessage()方法。
那么target又是哪里赋值的呢,我们先看Message的构造器,代码如下:

    // Message.class
    public Message() {
    }

发现并没有赋值target的值,我们回想一般在新建Message消息后我们会发送出来,我们去那个方法看下:

    // Handler.class
    public final boolean sendMessage(Message msg){
        return sendMessageDelayed(msg, 0);
    }

    public final boolean sendMessageDelayed(Message msg,
                             long delayMillis){
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(
        msg, SystemClock.uptimeMillis() + delayMillis);
    }

    public boolean sendMessageAtTime(Message msg, 
                                     long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            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);
    }

到最后我们可以发现target = this为我们当前的Handler,最后我们看下enqueueMessage方法,代码如下:

    // MessageQueue.class
    boolean enqueueMessage(Message msg, long when) {
        //...
        synchronized (this) {
            if (mQuitting) {
                return false;
            }

            msg.markInUse();
            msg.when = when;
            Message p = mMessages;
            boolean needWake;

            // mMessages可以理解为上一次Message
            // 当mMessages不为空,或者启动时间为0的,或者启动时间小于mMessages的启动时间
            if (p == null || when == 0 || when < p.when) {
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                // 循环将消息插入队列之中
                for (; ; ) {
                    prev = p;
                    p = p.next;

                    // 当下个无消息的时候
                    // 或者当前消息启动时间小于下个的启动时间,跳出循环
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p;
                prev.next = msg;
            }

            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

上述代码就是Message插入队列的代码。

总结:

Handler机制其实在Android机制中算比较好理解的,我们可以看到主要涉及的类有Handler,Looper,MessageQueue和Message。
在主线程中,
Handler:负责对外,比如消息的添加,移除等功能,
Looper:个人理解作为一个载体,承载着消息队列的启动,获取及销毁消息,使Handler不必对MessageQueue进行管理,专注处理对外事件的处理
MessageQueue:对消息的循环移除,及对C++代码的通信。其中涉及到部分的jni代码本篇暂时还没解析,有兴趣的同学可以自行了解或谷歌。
这也是本人的第一篇博客,如果有什么写的错误或者不足的,请大家留言帮忙纠错!0-0

你可能感兴趣的:(Android源码机制)