Android中的消息机制是学习andriod中比较难以理解的地方,理解好这一部分是灵活运用Handler的基础。
为什么使用handler?因为在android中,我们一般是不会在子线程中去操作图形界面的,典型的锂例子就是跟新进度条,改变进度条的值必须在主线程中进行。
学习消息机制之前先来介绍几个有关的类:
Message:
该类有几个用的比较多的属性 arg1,arg2,obj,what
官方解释:arg1 and arg2 are lower-cost alternatives to using setData()
if you only need to store a few integer values.
arg1,arg2可以用来传递比较简单整型数据,使用它比将数据放入Bundle中的效率要高
obj:用来传递任何一个对象
what:存放消息码,使得接受者可以识别消息
Handler:
官方解释:
A Handler allows you to send and process Message
and Runnable objects associated with a thread'sMessageQueue
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.
一个handler对象可以让Message对象和Runnable对象与一个线程的消息队列关联,每一个handler对象都和一个线程关联,当你创建一个handler,它就会与一个消息队列或者线程队列绑定,从那一刻起,它将会发送消息或者runnable到与他关联的队列,当消息或者runnable出队列时,就会被执行。
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, callprepare()
in the thread that is to run the loop, and thenloop()
to have it process messages until
the loop is stopped.
该类主要用于管理一个线程的消息循环,一个线程默认是loop与之关联,创建一Looper,首先要调用prepare(),然后调用loop()不断的处理消息直到loop停止。
现在来分析一下源代码:
Looper:
public static final Looper myLooper() {
return (Looper)sThreadLocal.get();
}
myLooper主要用于获得与当前线程对象关联的looper对象:
public synchronized static final Looper getMainLooper() {
return mMainLooper;
}
getMainLooper用户获得与主线程关联的looper对象
注意:如果在主线程中调用myLooper那么这两种方法获得的对象时一样的
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
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);
msg.recycle();
}
}
}
这是一个死循环,主要是从该线程的消息队列中不断的区消息,并发送给与之关联的handler对象。注意其中的msg.target.dispatchMessage(msg);msg.target就是与之关联的Handler对象。
Handler对象:
public Handler() {
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 = null;
}
通过以上的代码,我们发现handler中的消息队列和一直关联的looper中的消息队列是同一个。
总而言之。每一个线程都有一个消息队列,而这个消息队列是交给与之关联的looper对象来管理的,而每个handler中又包含一个looper对象,所以他们操作的消息队列其实是一个。