你的位置:首页 > 操作系统

[操作系统]Handler机制(三)


一、Looper

Looper对象,顾名思义,直译过来就是循环的意思,从MessageQueue中不断取出message。

Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.

1.Looper的成员变量:

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();private static Looper sMainLooper; // guarded by Looper.classfinal MessageQueue mQueue; //一个MQfinal Thread mThread;  //一个thread

Looper的代码是非常简单的。在官方文档的注释中,它推荐我们这样来使用它:

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

先看看prepare方法。

Looper.prepare

public static void prepare() {    prepare(true);  }  private static void prepare(boolean quitAllowed) {    if (sThreadLocal.get() != null) {//每个线程只能有一个looper      throw new RuntimeException("Only one Looper may be created per thread");    }    //设置本线程的looper。    sThreadLocal.set(new Looper(quitAllowed));  }

  注意prepare(boolean)方法中,有一个sThreadLocal变量(ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本),这个变量有点像一个哈希表,它的key是当前的线程,也就是说,它可以存储一些数据/引用,这些数据/引用是与当前线程是一一对应的,在这里的作用是,它判断一下当前线程是否有Looper这个对象,如果有,那么就报错了,"Only one Looper may be created per thread",一个线程只允许创建一个Looper,如果没有,就new一个。然后它调用了Looper的构造方法。

Looper 的构造方法

在上边调用了构造方法:Looper(quitAllowed),初始化了messageQueue并绑定当前线程。

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

此时的初始化动作已经结束了,接下来看Looper.loop():

 

public static void loop() {    final Looper me = myLooper();//返回当前的looper    if (me == null) {      throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");    }    final MessageQueue queue = me.mQueue;//取得messageQueue        for (;;) {      Message msg = queue.next(); // might block      if (msg == null) {        // No message indicates that the message queue is quitting.        return;      }      。。。。      msg.target.dispatchMessage(msg);      。。。      msg.recycleUnchecked();    }  }

 

loop()方法,省去了一些不关心的部分。剩下的部分非常的清楚了,首先调用了静态方法myLooper()获取当前Looper对象。没有looper则抛出异常。

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

1. myLooper()同样是静态方法,它是直接从这个ThreadLocal中去获取Looper对象,拿到当前线程的Looper后;

2. MessageQueue queue = me.mQueue;拿到与这个Looper对应的MQ,就开始无限循环,不断的从消息队列中取出Message,当获取到一个消息后,它调用了Message.target.dispatchMessage()方法来对消息进行处理。dispatchMessage这个方法在Handler中,就是处理message。

3.msg.recycleUnchecked(),当这个msg处理完了,就没有用啦,把它回收到全局池中,注意不是销毁。

总结

Looper的代码看完了,我们得到了几个信息:

  • Looper调用静态方法prepare()来进行初始化,一个线程只能创建一个与之对应的LooperLooper初始化的时候会创建一个MQ,并和当前线程绑定,因此,有了这样的对应关系,一个线程对应一个Looper,一个Looper对应一个MQ。

  • Looper调用静态方法loop()开始无限循环的取消息,messageQueue调用next()方法来获取消息(这也是个无限循环)。

MessageQueue源码解析:http://www.cnblogs.com/jycboy/p/5786682.html

 

Message源码解析:http://www.cnblogs.com/jycboy/p/5786551.html