最近的工作涉及了Android的Handler消息传递,总结如下:
1. Handler :
为了实现线程和Activity中widget之间的通信,比如为了进行某些耗时操作而新开的线程,在这些操作中如果要跟新UI则需要Handler来处理。它主要负责Message的分发和实现不同Message操作的自定义,相当于句柄。
2. MessageQuene:
Message是线程和widget通信的介质,也就是来传递信息的,显然MessageQuene则是保存Message的列表,在代码中表现为ArrayList。
3. Looper:
是一个控制器,它不断的从MessageQuene中取Message,然后将Message传递给Handler中的handleMessage方法以实现用户自定义操作。
一个线程只能有一个Looper,线程中可能有多个Handler,一个Looper管理一个MessageQuene,不同线程的Looper由ThreadLocal管理。
整个工作流程如下:
1. 线程工作流程
线程注册Looper =>
线程注册Handler=>
Handler sendMessage 到 MessageQuene
2. Looper工作流程
在Looper.prepare()中Looper被注册 =>
Looper执行Looper.loop() 取MessageQuene中的Message,执行Message的Handler(句柄)的handlerMessage方法,实现自定义操作。 =>
Looper的管理通过ThreadLocal类实现,ThreadLocal机制:为不同线程管理变量副本,实现多线程异步操作。
源码分析如下:
1. 调用流程
public class HelloAndroidActivity extends Activity {
Handler handler = new Handler() {//根据返回Message自定义操作
public void handleMessage(Message msg) {
......
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Thread thread = new Thread() {
public void run() {
Looper.prepare();//注册Looper
........
Looper.loop();//Looper开始操作MessageQuene
handler.sendMessage(new Message());//发送消息到MessageQuene
}
};
thread.start();//启动线程
}
}
2. Handler 分析
/**
* A Handler allows you to send and process {@link Message} and Runnable
* objects associated with a thread's {@link MessageQueue}. Each Handler
* instance is associated with a single thread and that thread's message
* queue. When you create a new Handler, it is bound to the thread /
* message queue of the thread that is creating it -- from that point on,
* it will deliver messages and runnables to that message queue and execute
* them as they come out of the message queue.
*/
public class Handler {
/**
* Subclasses must implement this to receive messages.
*/
public void handleMessage(Message msg) {
}
/** 初始化handler,确认Handler的mLooper, mQueue,callback等等
* and set whether the handler should be asynchronous.* Use the {@link Looper} for the current thread with the specified callback interface
*
* Handlers are synchronous by default unless this constructor is used to make
* one that is strictly asynchronous.
*
* Asynchronous messages represent interrupts or events that do not require global ordering
* with represent to synchronous messages. Asynchronous messages are not subject to
* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
*
* @param callback The callback interface in which to handle messages, or null.
* @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
*
* @hide
*/
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;
} /** * Handle system messages here. */在Looper.loop()中会调用这个函数,实现handle message public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } /** * Default constructor associates this handler with the queue for the * current thread. * * If there isn't one, this handler won't be able to receive messages. */ public Handler() { mLooper = Looper.myLooper();//获取该线程Looper if (mLooper == null) {//确保该线程已注册Looper throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = null; } /** * Returns a new {@link android.os.Message Message} from the global message pool. More efficient than * creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this). * If you don't want that facility, just call Message.obtain() instead. */获取消息,比new效率高 public final Message obtainMessage() { return Message.obtain(this); } /** * Causes the Runnable r to be added to the message queue. * The runnable will be run on the thread to which this handler is * attached. * * @param r The Runnable that will be executed. * * @return Returns true if the Runnable was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */ public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } /** * Pushes a message onto the end of the message queue after all pending messages * before the current time. It will be received in {@link #handleMessage}, * in the thread attached to this handler. * * @return Returns true if the message was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */网MessageQuene中加入消息 public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } /** * Remove any pending posts of messages with code 'what' that are in the * message queue. */ public final void removeMessages(int what) { mQueue.removeMessages(this, what, null, true); }} 3. Looper分析/** * Class used to run a message loop for a thread. Threads by default do * not have a message loop associated with them; to create one, call * {@link #prepare} in the thread that is to run the loop, and then * {@link #loop} to have it process messages until the loop is stopped. */ public class Looper { Thread mThread; private static Looper mMainLooper = null; /** Initialize the current thread as a looper. * This gives you a chance to create handlers that then reference * this looper, before actually starting the loop. Be sure to call * {@link #loop()} after calling this method, and end it by calling * {@link #quit()}. * 为进程注册Looper,并确保每个进程一个Looper, * ThreadLocal为不同进程分别管理相应Looper */ public static final void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper()); } /** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. * 不停的取message,并调用其Handler. */ public static final void loop() { Looper me = myLooper(); 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(); while (true) { Message msg = queue.next(); // might block //if (!me.mRun) { // break; //} if (msg != null) { if (msg.target == null) { // No target is a magic identifier for the quit message. return; } if (me.mLogging!= null) me.mLogging.println( ">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what ); msg.target.dispatchMessage(msg); if (me.mLogging!= null) me.mLogging.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(); msg.recycle(); } } } /** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. * 获取当前线程Looper */ public static final Looper myLooper() { return (Looper)sThreadLocal.get(); } }