Looper:循环器,是一个用于使线程运行一个消息(Message)循环的类。线程默认没有关联的消息循环,在建立它以前,在将要运行循环的线程中调用prepare方法,而后loop方法会处理消息直到循环结束。 java
绝大多数消息循环是经过Handler类来Looper交互的。 ide
下面是实现了Looper的线程的一个典型例子,使用分离的prepare方法和loop方法来建立一个用于跟Looper沟通的初始Handler。 oop
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方法: ui
public static final void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper()); }
每条线程只能绑定一个Looper,不然会抛出RuntimeException异常。若是不调用prepare方法,sThreadLocal.get()就会返回null。注意这是个静态方法,在最后一行中绑定了一个作为Looper的线程。怎么绑定的呢,看看Looper的一个私有无参构造方法: spa
private Looper() { mQueue = new MessageQueue(); mRun = true; mThread = Thread.currentThread(); }
构造方法里初始化了一个消息队列、一个运行状态的标志以及绑定一个线程(建立者所在的线程)。prepare方法给了一个在真正的循环开始以前,参照Looper建立一个Handler的机会。注意:在run方法中初始化Handler以前,必须调用Looper.prepare(),否则会抛出一个运行时异常,由于Handler须要一个从Looper获得的消息队列(即构造方法里面的mQueue)。调用prepare方法后必定要调用loop方法,而且调用quit方法退出循环。 线程
接下来,看看在当前线程里运行一个消息队列的loop方法,用完后必定要调用quit方法结束循环: code
public static final void loop() { Looper me = myLooper(); MessageQueue queue = me.mQueue; 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; } msg.target.dispatchMessage(msg); msg.recycle(); } } }
高潮来了,上面说过,Looper的mQueue是Handler使用的消息队列,loop方法启动一个死循环从队列中获取数据,当队列中没有数据时,queue.next()会阻塞。当有数据时,msg.target(即Handler)就会调用dispatchMessage方法,进而调用Handler的handleCallback或者handlerMessage方法。从这些也能够知道,若是Handler是在子线程的run方法中建立(以前必须调用Looper.prepare())的,那么这个Handler的handleMessage或者handleCallback方法就是运行在子线程的。 队列