android Handler Looper,MessageQueue消息机制原理
安卓消息处理类:
Looper、Handler、MessageQueue、Message、ThreadLocal、ThreadLocal.Values、HandlerThread。
Looper:
线程默认是没有消息循环的,要为一个线程创建一个消息循环通过调用prepare(),然后在调用loop()方法进入消息循环(这意味着线程将一直在此方法循环)。例如:
- 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();
- }
- }
那么Looper如何管理每一个线程对应的一个looper的呢?
- public final class Looper {
- // sThreadLocal.get() will return null unless you've called prepare().
- static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
- private static Looper sMainLooper; // guarded by Looper.class
- final MessageQueue mQueue;
- final Thread mThread;
- private Printer mLogging;
- 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));
- }
- public static void prepareMainLooper() {
- prepare(false);
- synchronized (Looper.class) {
- if (sMainLooper != null) {
- throw new IllegalStateException("The main Looper has already been prepared.");
- }
- sMainLooper = myLooper();
- }
- }
- public static Looper getMainLooper() {
- synchronized (Looper.class) {
- return sMainLooper;
- }
- }
- 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;
- Binder.clearCallingIdentity();
- final long ident = Binder.clearCallingIdentity();
- for (;;) {
- 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);
- }
- 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();
- }
- }
- public static Looper myLooper() {
- return sThreadLocal.get();
- }
下面通过图解讲解上面的过程:(prepare调用threadLocal的get的set方法)
Handler类:
构造函数:
1)Handler handler = new Handler(),内部会调用 public Handler(Callback callback, boolean async)方法,将Handler的成员变量mLooper和mQueue赋值为当前线程的looper对象和对应的消息队列,如果当前线程没有looper会抛出异常。
2)Handler handle = new Handler(Looper looper),内部会调用public Handler(Looper looper, Callback callback, boolean async),将参数的looper对象传递给handler的mHandler对象,mQueue对象赋值。通过此方法可以在其它线程中为主线程创建Handler,例如:new Handler(Looper.getMainLooper());
handler的sendMessage()方法,在内部会将handler对象赋值为Message的mTarget中,然后调用mQueue将消息发送到线程的消息队列中。
Message类:
Message类内部会保存一个Handler对象mTarget。
Looper的loop方法,取出消息,然后调用Message对象中的handler的dispatchMessage方法,dispatchMessage根据callback是否为空执行handleMessage方法。
流程图如下:
HandlerThread是一个可以简单创建一个进行消息处理的线程类。
总结:
1)Thread最多与一个looper建立联系。
2)一个looper有且仅有一个MessageQueue
3)一个handler只能与一个looper关联
4)一个Message只能与一个handler关联
这四个一对一的关系使得消息发送和处理得到正确的相应。

浙公网安备 33010602011771号