一、用法。
Looper为了应付新闻周期,在创建过程中初始化MessageQueue。
Handler在一个消息到当前线程的其他线程
MessageQueue用于存储所述消息
Looper其中线程创建的对象。Handler的handleMessage方法就在哪个线程运行
在创建activity时,android系统本身会为activity创建Looper。
final Handler mainHandler = new Handler(getMainLooper()){ @Override public void handleMessage(Message msg) { String content = "当前线程:" + "msg:" + msg.what; Toast.makeText(MainActivity.this, content, Toast.LENGTH_SHORT).show(); }};mainHandler.sendEmptyMessage(0x1);在其他线程中使用 handler 消息传递时,必须自己创建 looper 。以下的样例中 HandlerThread 封装了 Looper 和 MessageQueue ,还实现了获取 Looper 的同步机制,比較好用。
HandlerThread mThread = new HandlerThread("MyThread");mThread.start();Handler mHandle = new Handler(mThread.getLooper()){ @Override public void handleMessage(Message msg) { String content = "当前线程:" + Thread.currentThread().getName() + "msg:" + msg.what; System.out.println(content); }};mHandle.sendEmptyMessage(0x2);
二、Looper解析
构造函数:
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mRun = true; mThread = Thread.currentThread();}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));}在prepare中创建了Looper实例。并在Looper的构造函数中创建了MessageQueue
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 (;;) { 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 msg.target.dispatchMessage(msg); // Make sure that during the course of dispatching the // identity of the thread wasn't corrupted. final long newIdent = Binder.clearCallingIdentity(); msg.recycle(); }}
在loop()中。Looper不断的通过queue.next()从MessageQueue取消息,然后调用语句msg.target.dispatchMessage(msg) 来运行。这里target为msg消息的发送者Handler,在分析Handler时再来分析。dispatchMessage在普通情况下会调用Handler类的handleMessage来处理消息。也就是上面样例中我们重载的这个handleMessage。
三、Handler解析
Handler的构造函数有非常多,这里选带Looper參数的构造函数public Handler(Looper looper) { this(looper, null, false);}public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async;}再看sendMessage。
public final boolean sendEmptyMessage(int what){ return sendEmptyMessageDelayed(what, 0);}public final boolean sendEmptyMessageDelayed(int what, long delayMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageDelayed(msg, delayMillis);}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);}private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis);}
sendEmptyMessage将message加到了Looper的MessageQueue中,之后Looper在loop()中调用queue.next()
在enqueueMessage里面。我们看到了msg.target = thispublic void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); }}
假设没有设置Callback的话,就会执行handleMessage了。
四、HandlerThread解析
HandlerThread继承于Thread,对Looper的操作进行了封装,做了同步处理。public void run() { mTid = Process.myTid(); Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); mTid = -1;}public Looper getLooper() { if (!isAlive()) { return null; } // If the thread has been started, wait until the looper has been created. synchronized (this) { while (isAlive() && mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper;}