Looper

来自个人维基
跳转至: 导航搜索

Looper的作用是在一个线程(thread)中循环取出消息并分发到对应的处理函数中去。

线程通常是没有与之相关联的消息looper的,通过这个类则可以实现这一功能:

1、在目的线程中调用prepare,创建一个looper并关联之

2、调用loop使looper开始工作,开始消息的分发工作

looper与所处理的消息大部分的交互都是通过 Handler这个类来实现的。

典型的用法:

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

应用程序使用:

    new LooperThread().start();

一、prepare函数

 /** Initialize the current thread as a looper.
  * This gives you a chance to create handlers that then reference
  * this looper, before actually starting the loop. Be sure to call
  * {@link #loop()} after calling this method, and end it by calling
  * {@link #quit()}.
  */
public static void prepare() {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper());
}

sThreadLocal的定义:

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

ThreadLocal是jdk中的一个线程局部变量类,这里表示sThreadLocal是一个线程局部变量,即线程中均保持其独立的副本。

而prepare中作做的则是创建了一个新的Looper并把这个对象赋予了线程局部变量sThreadLocal。

二、loop函数

/**
 * Run the message queue in this thread. Be sure to call
 * {@link #quit()} to end the loop.
 */
public static void loop() {
    Looper me = myLooper();
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    MessageQueue queue = me.mQueue;

    Binder.clearCallingIdentity();
    final long ident = Binder.clearCallingIdentity();
    
    while (true) {
        Message msg = queue.next(); // might block
        if (msg != null) {
            if (msg.target == null) {
                // No target is a magic identifier for the quit message.
                return;
            }

            long wallStart = 0;
            long threadStart = 0;

            msg.target.dispatchMessage(msg);

            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }
            
            msg.recycle();
        }
    }
}

此函数的工作就是不停地从线程局部变量sThreadLocal中不断地取出消息,并分发,我们再来看一下分发函数:

//Handler.java
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {  //如果msg自带有callback
            handleCallback(msg);  //调用自带的callback
        } else {  //否则
            if (mCallback != null) {  //如果handler自带有callback
                if (mCallback.handleMessage(msg)) {  //调用handler自带的callback
                    return;
                }
            }
            handleMessage(msg);  //调用关联handler的handleMessage
        }
    }