【Android】02. 循环取消息的 Loop 和 发送消息的Handler

278 阅读2分钟

在 ActivityThread 的主程序启动的时候,我们发现 main 方法里面有个 Looper 的 loop() 方法,查看源码会发现里面是个死循环;这样保证应用程序一直在执行;

loop() 源码

public static void loop() {
        final Looper me = myLooper();
        // 省略一些代码.......

        for (;;) {
            // 1. 从消息队列里面拿出一个消息
            Message msg = queue.next(); // might block

            // 2. 让消息的 target 处理(分发)消息
            msg.target.dispatchMessage(msg);

            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }
            // 省略一些代码.......
            // 3.处理完后回收
            msg.recycle();
        }
}

从代码上理解,就这3步;

  1. 取出消息
  2. 处理消息 (这里注意 target 是 Handler)
  3. 回收消息

从上面3点可以得出几个结论;

  1. 肯定有地方去添加消息队列 queue;
  2. 队列里面的元素是 Message;
  3. 每个 Message 应该有个 Handler;

把消息添加到队列

android.os.MessageQueue#enqueueMessage

// 加入队列的操作
boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }
        // 省略一些代码.......
}

上面代码可以看出,每个Message必须要有 target (handler类型);且不能被用过;那说明时候被添加呢?在来看一段常用的代码;

// 这是一段 hanlder 发送消息的代码
myHandler.sendMessage(message);
...........
.............
// 以上是一段 Handler 发送消息的代码,最终都会到达 Handler 的 
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        // 这个地方把 handler 放进 Message 中
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        // 这个地方把队列放进去
        return queue.enqueueMessage(msg, uptimeMillis);
    }

结论和总结

当一个 App 启动的时候默认会执行 ActivityThread 的 main 方法;生成应用程序的第一个线程,且创建了一个 Loop, 并执行了 loop() 方法;根据这个 loop 的特性,这个线程就一只执行下去。这个 loop() 的主要作用就是

  1. 取出消息;2. 处理消息 ;3. 回收消息;这样程序就只要等待一些消息过来然后处理就好了;所以理论上来说
1 个 app 对应一个 ActivityThread
1 个 ActivityThread 对应一个 Loop
1 个 Loop 对应一个消息队列(MessageQueue)
1 个 MessageQueue 对应多个 Message 
1 个 Message 必须有1个 handler

其实 Message 是个链表,它有 next 的属性;先简单认为是个队列吧。

从上面结论可以看出,如果 MessageQueue 里面的 Message 如果不及时处理,那么会有一些问题;

  1. 如果队列中有一个 Message 处理时间很长,那么就会影响到后面的 Message 的处理,比如后面都是一些界面刷新操作;那么很有可能不及时了
  2. 如果被阻塞的 Message 的 Handler 有对大对象的引用(Context, Activity, Fragment, View), 那么很有可能会出现内存泄露;