Android面试-5 Android消息机制

消息机制概述

Handler

利用当前线程的Looper创建内部消息循环系统,主要负责发送和处理消息。另外,也可以通过一个Looper创建一个Handler,这样handler发送的消息就会在Looper所在的线程执行。当我们使用Handler的时候,通过post或者send的一些列方法时,实际上是把一个Message(消息)添加到MessageQueue(消息队列)中去。

MessageQueue

以队列的形式(内部存储结构为单链表)存储和操作消息列表,包含插入和读取消息两个操作,读取是一个无限循环的方法,若消息队列没有消息则一直阻塞,有消息则读取并将其移除

Looper

无限循环地检查MessageQueue是否有新消息,有的话就取出来给Handler处理,否则一直阻塞等待。一般线程默认是没有Looper,若要使用需先创建Looper.prepare(),然后创建Handler,然后Looper.loop()开启消息循环,Looper是运行在Handler所在的线程中的,通过Loop.myLooper()得到当前线程的Looper对象,Handler会使用ThreadLocal来获取当前线程的Looper。若要退出Looper可以采用quit或quitSafely(会清空所有延时消息,处理完消息队列中的非延时消息后再退出)。

Looper类中维护一个消息队列MessageQueue和一个ThreadLocal类型的对象,在Looper的构造函数中对MessageQueue进行了初始化。static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

    private static Looper sMainLooper;  // guarded by Looper.class
    final MessageQueue mQueue;
    final Thread mThread;

一个线程只允许存在一个looper对象。而且该对象存储在ThreadLocal里面,若果创建两个Looper则会出现运行时异常,看源码:

 public static void prepare() {
         prepare(true);
   }
private static void prepare(boolean quitAllowed) {
      // 这里是关键,如果这个线程已经存在Looper报异常
     if (sThreadLocal.get() != null) {
         throw new RuntimeException("Only one Looper may be created per thread");
     }
      // 不存在,创建一个Looper设置到sThreadLocal
      sThreadLocal.set(new Looper(quitAllowed));
 }

主线程的消息循环

在ActivityThread的main方法中通过Looper.prepareMainLooper()创建主线程的Looper及MessageQueue,并通过looper.loop()开启主线程消息循环。

主线程为什么不会因为Looper.loop()循环卡死?

主线程再进入消息循环前,会创建一个Linux管道,可以让主线程再消息队列为空时进入空闲等待状态,当消息队列有消息需要处理时再唤醒主线程。

阅读更多
个人分类: Android面试
所属专栏: Android面试
上一篇Android面试-4 ContentProvider
下一篇Android面试-7 多线程
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭