最近又复习了Handler,Message,MessageQueue,Thread,Looper,记录一下。
Looper类
Looper类在消息机制中扮演着消息循环的角色,默认的线程没有与之相关的消息循环,创建消息循环,需要在线程中调用Looper类的prepare()方法创建,然后调用loop()方法让它循环处理消息。
Looper类的构造函数源码:
<span style="font-size:14px;">private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}</span><span style="font-size: 12px;">
</span>
在Looper的构造方法中创建了一个MessageQueue即消息队列,然后将消息队列mQueue和当前线程对象mThread保存起来。
一个典型的例子,使用prepare()和loop()分离来创建一个初始的Handler来与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();
}
}
loop()方法源码:
<span style="font-size:14px;"> 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;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {
<strong> Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
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.recycleUnchecked();
}
}</span>
Looper类的loop方法的工作过程:
首先调用Looper类的myLooper方法获取Looper对象me;
然后me.mQueue获取消息队列queue;
loop方法是一个死循环,通过MessageQueue的next方法来获取新消息msg,如果MessageQueue的next方法返回了null,那么消息队列退出。MessageQueue的next是一个阻塞操作,当没有消息时,next方法会一直阻塞在那里,如果MessageQueue返回了新消息,则会调用msg.target.dispatchMessage(msg),这里的msg.target是一发送这条消息的Handler对象,这样Handler发送的消息最终又交给它的dispatchMessage方法处理了。
Looper类常用方法:
public static void prepare () //初始化当前线程作为一个Looper,这给你机会创建handlers,然后引用这个looper,调用loop()启动循环,调用quit()结束循环。
public static void loop () //运行线程的消息队列,一定要调用quit()方法结束循环;
public static Looper getMainLooper () //返回应用程序的main looper,存在于应用程序的主线程。
public MessageQueue getQueue () //获取循环的消息队列
public Thread getThread () //获取与Looper相关的线程
public boolean isCurrentThread () //如果当前线程是这个looper的线程返回true
public static Looper myLooper () //返回与当前线程相关的Looper对象,如果调用Looper.loop()的线程与Looper不相关返回null。
public static MessageQueue myQueue () //返回与当前线程关联的消息队列,这必须从一个线程中被调用来运行一个Looper,否则抛出空指针异常。
总结:
Looper的创建在线程内,Looper内部保存消息队列和当前线程;
创建并启动消息循环,通过调用Looper的两个静态方法prepare()和loop()。
类。
Handler类
位于android.os.Handler包
Handler发送和处理与一个线程的消息队列关联的Message和Runnable对象。每个Handler实例与一个线程和消息队列关联。当你创建一个新的Handler时,它发送messages和runnables到消息队列,当messages和runnables从消息队列中取出来,由handler处理消息。
两大主要使用:
(1) to schedule messages and runnables to be executed as some point in the future;
and (2) to enqueue an action to be performed on a different thread than your own.
Scheduling messages 使用以下方法:
sendMessageAtTime(Message, long)
,
sendMessageDelayed(Message, long)
Thepost 版本允许你排队 Runnable 对象,这些对象将由消息队列调用;
the sendMessage版本允许你排队 Message
对象,Message对象包含书,将由Handler的handleMessage(Message)
方法处理。(r要求你实现一个Handler的子类).
当发送Runnable或Message给一个Handler时, 你可以允许消息队列立即开始处理或者延迟处理,允许你实现超时,时间间隔或其他计时行为。
当应用程序的一个进程被创建时,它的主线程致力于运行一个消息队列,这个消息队列负责管理顶级应用程序对象 (activities, broadcast receivers, etc) and any windows they create. 你可以创建自己的线程,并且通过Handler与主应用程序线程交互。 这通过在你自己新创建的线程中调用post orsendMessage方法, Runnable or Message 然后将被在Handler的消息队列中排队,合适时机处理。
Handler类常用方法有:
public void dispatchMessage(Message msg) //处理系统消息
public void handleMessage(Message msg) //子类必须实现这个方法来接收消息
public final Looper getLooper ()
public final Message obtainMessage () //从全局消息池中返回一个新消息对象,比创建和分配新实例更有效。获得的消息实例有对应的Handler,如果
public final Message obtainMessage (int what, int arg1, int arg2) //与obtainMessage()除了设置了what,arg1,arg2参数外,用法几乎相同。
还有其他obtainMessage方法,不一一列举了。可以参考官方API文档。publicHandler() //默认构造函数,将handler与当前线程的Looper连接,如果线程没有looper,这个handler不能接收消息,将抛出异常。
publicHandler(Handler.Callback callback)
publicHandler(Looper looper) //
publicHandler(Looper looper,Handler.Callback callback)
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
private static void handleCallback(Message message) {
message.callback.run();
}
public final boolean hasCallbacks(Runnable r) {
return mQueue.hasMessages(this, r, null);
}
public final void removeMessages(int what) {
mQueue.removeMessages(this, what, null);
public static Message obtain (Handler h, int what);
public static Message obtain (Handler h, int what, Object obj);
public void setData (Bundle data);
public void sendToTarget (); //发送Message到与此相关的Handler对象
Message msg = handler.obtainMessage();
msg.what = LOCAT_ERROR;
msg.obj = message;
msg.sendToTarget();
obj 发送给接收者的任意对象。