Looper是android为线程间异步消息通信提供的一种机制,利用Looper机制可以方便我们实现多线程编程时线程间的相互沟通。当然,如果不用Looper而采用其它的线程间通信方式(像管道,信号量,共享内存,消息队列等)也是一样的。Looper的实现是利用消息队列的方式,为用户封装了一层API,用户不需要考虑互斥加锁的问题,方便用户的使用。
(1) Looper的使用方法:
如果我们想创建一个新的线程来执行新的任务,此时我们需要定义新的线程和创建新的线程对象;如果只是在当前线程增加异步消息处理,则不需要创建新的线程。更多的使用情况是创建新的线程,利用新的线程执行单独的新任务。
//定义handler
public class Workhandler extends Handler {
public Workhandler(Looper looper) {
super(looper);
}
public void handleMessage(Message msg) {
switch(msg.what) {
case x:
break;
case y:
break;
default:
break;
}
}
} //定义线程
private class TestHandlerThread extends Thread {
TestHandlerThread() {
super("TestThread");
}
@Override
public void run() {
Looper.prepare();//必须在Looper.myLooper()之前
Looper looperTest = Looper.myLooper();
mWorkHandler = new Workhandler(looperTest);//mWorkHandler属于新创建的线程
Looper.loop();
}
}
使用:
TestHandlerThread testThread = newTestHandlerThread();
Message message = Message.obtain();
message.arg1 = 1111;
message.what = x;
mWorkHandler.sendMessage(message);//此时是在另一个线程,通过直接访问新线程中的变量向 TestHandlerThread发送消息
(2)Looper原理分析:
static final ThreadLocal
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));//创建Looper对象,所以prepare必须放在最前面
}
ThreadLocal的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变量的传递的复杂度。在这里的作用是,它判断一下当前线程是否有Looper
这个对象,如果有,那么就报错,"Only one Looper may be created per thread",一个线程只允许创建一个Looper
,如果没有,就new一个新的塞进sThreadLocal中。然后它调用了Looper
的构造方法。
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
Looper构造方法中创建了一个MessageQueue,且保存了此MessageQueue的引用,此MessageQueue属于Looper所在的线程。
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
msg.target.dispatchMessage(msg);
}
}
loop()是一个死循环,不断的从当前线程的MessageQueue中取数据,调用msg目标的dispatchMessage()。
下面我们看一下workhandler中的sendMessage函数
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
workHander属于新的线程,所以queue为刚才线程的Looper创建的queue,即向目标线程的MessageQueue中放入一个新的消息。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;//设置消息的处理者
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
此时loop()正在不断循环等待消息的到来,Looper从MessageQueue中获取到消息后,调用 msg.target.dispatchMessage(msg);即为workHander的dispatchMessage()函数
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
因为我们没有定义CallBack函数,最后调到我们自定义的handleMessage()函数。