转载

Handler机制(三)----Looper源码解析

一、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.class

final MessageQueue mQueue;  //一个MQ
final 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

原文  http://www.cnblogs.com/jycboy/p/5787443.html
正文到此结束
Loading...