Android中的MessageQueue,Handler,Looper和Thread

<script type="text/javascript"> document.body.oncopy = function() { if (window.clipboardData) { setTimeout(function() { var text = clipboardData.getData(&quot;text&quot;); if (text &amp;&amp; text.length &gt; 300) { text = text + &quot;\r\n\n本文来自CSDN博客,转载请标明出处:&quot; + location.href; clipboardData.setData(&quot;text&quot;, text); } }, 100); } } </script><script type="text/javascript"> function StorePage() { d = document; t = d.selection ? (d.selection.type != 'None' ? d.selection.createRange().text : '') : (d.getSelection ? d.getSelection() : ''); void (keyit = window.open('http://www.365key.com/storeit.aspx?t=' + escape(d.title) + '&amp;u=' + escape(d.location.href) + '&amp;c=' + escape(t), 'keyit', 'scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes')); keyit.focus(); }</script>


转载时请注明出处和作者联系方式
文章出处:http://www.limodev.cn/blog
作者联系方式:李先静 <xianjimli at hotmail dot com>

前几天和一位同事讨论Android中Handler和Thread,其中一个问题是:创建Handler时会不会创建Thread?

我对JAVA编程不熟,但直觉告诉我不会:我认为Handler只是用来辅助实现异步操作的东西。当时我拿了GTK+中的idle来做对 比,sendMessage就相当于加一个idle函数,系统处理完前面的Message后就会处理这个Message。毕竟没有看过里面的实现代码,所 以当时并不确信。今天看了下:

MessageQueue

消息队列MessageQueue是一个以执行时间为序的优先级队列:

o 普通消息的执行为当前时间,先发送的前面,后发送在后面,这是典型的FIFO。

o 最高优先级的消息执行时间为0,所以直接插在队列的最前面,通常会立即执行。

o 而在将来执行的Message相当于timer,执行时间为当前时间+delay的时间。

MessageQueue的函数boolean enqueueMessage(Message msg, long when)用来向队列中插入消息。

Message和GTK+ idle不同之处在于,Message只是一段数据,里面说明了要做什么,但不并知道如何做。而idle带有自己的数据和处理函数,它知道如何做。Message放入队列中后,在处理这些消息时到底要做些什么呢?这就引入了Handler:

Handler

Handler 对消息队列的enqueueMessage做了包装,这其实并不重要,因为完全可以直接调用enqueueMessage来实现。重要的Handler把 在包装enqueueMessage的同时,把Message的target设成了自己,即为Message指定执行的行为:

if (queue != null) {
msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);
}

这样一来,当前Message被处理的时候就会调用Handler的dispatchMessage,而这个函数就会调用你要实现的虚函数handleMessage了。经过消息队列转了一圈,还是调用了你自己的实现函数,但是同步操作变成了异步操作。

public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}

Looper

Message放在消息队列里了,谁来一个一个的取出来处理呢?这时轮到Looper上场了,它的函数loop会一直循环处理队列中的消息,直到遇上一个没有target的Message:

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();
}
}
}

由此可见:一个Looper总是和一个MessageQueue关联起来的。

Thread

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也总是和一个Thread关联起来的,不过不一定要创建新线程,可以是主线程的。Handler和Thread不是一一对应的,理论上, 在一个LooperThread中,可以有任何多个Handler,每个消息都可以指定不同的Handler,因为每个消息都可以有不同的行为。

在创建Handler时并不会创建Thread,它只是取当前线程的Looper的MessageQueue:

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;
}

通过myLooper取出当前线程的Looper:

public static final Looper myLooper() {
return (Looper)sThreadLocal.get();
}

这个Looper是在Looper.prepare里创建的:

public static final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}

更多相关文章

  1. Android中消息机制中一些细节知识点
  2. C语言函数以及函数的使用
  3. Android 蓝牙(BLE)连接,发送,接收消息
  4. 【Android自助餐】Handler消息机制完全解析(一)Message中obtain()
  5. 【幻灯片分享】Android消息推送实现 | 友盟 徐仙明 | Android De

随机推荐

  1. QT项目编译Android(安卓)版本时,错误合集
  2. Android开发者必备的十大开发工具
  3. Android之drawBitmap方法
  4. Android 多媒体【转】
  5. Android视频编码器
  6. Android Studio 快速定位错误行
  7. android的RTL支持
  8. ArcGIS Runtime SDKs v10.2.4最新(Android
  9. android 自定义控件之一
  10. Android 8.0的WIFI 架构差异分析