虽然MessageQueue提供了直接读/写的函数接口。但对于程序猿来说,一般不直接读/写消息队列。之前了解到,在Looper.loop()函数中。当取出消息后,会回调msg.target对象的handleMessage()函数。而msg.target的类型正是Handler。

    /**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
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类向消息队列中发送消息,并重载Handler类的handleMessage()函数加入消息处理代码。

Handler对象仅仅能加入到有消息队列的线程中,否则会发生异常。以下代码是Handler类的构造函数:

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

注意这句代码:

        mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}

由以上代码能够得出结论,在构造Handler对象前。必须已经运行过Looper.prepare(),但prepare()不能被运行两次。

以下是Looper.prepare()的代码:

     /** 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()}.
*/
public static final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}

创建Handler对象能够在运行Looper.loop()函数之前。也能够在运行之后。

在以往的应用程序开发中,一般在Activity的初始化代码中加入Handler对象。其实,在Activity对象被构造前,Activity所在的线程已经运行了Looper.prepare()函数。详细可查看以下的链接。

http://blog.csdn.net/manoel/article/details/39499747

一个线程中能够包括多个Handler对象。在Looper.loop()函数中。不同的Message相应不同的Handler对象,从而回调不同的handleMessage()函数。

最新文章

  1. nodejs+edatagrid读取本地excel表格
  2. PDFobject插件使用,PDF在线查看插件
  3. 【C#】时间戳转换
  4. BZOJ-2049 Cave洞穴勘测 动态树Link-Cut-Tree (并查集骗分TAT)
  5. Git与Repo入门(转载)
  6. 目前几款基于html5的前端框架:如Bootstrap、Foundation、Semantic UI 、Amaze UI
  7. BAT文件执行完成后如何删除自身的解决办法
  8. 第三个Sprint冲刺第二天 最终篇
  9. Linux manual中命令标号的含义
  10. SSDP 简单服务发现协议
  11. 搭建自己的NuGet服务器,上传自定义NuGet包
  12. Android进阶笔记03:Android应用中实现查看&quot;附近的人&quot;的功能
  13. filter过滤器执行顺序
  14. 2016 ACM/ICPC Asia Regional Qingdao Online
  15. hibernate之查询
  16. Spring基础(4) : bean重写
  17. excel、xls文件读写操作
  18. streaming优化:并行接收数据
  19. 泊松分布E(X^2)
  20. Spring JavaConfig

热门文章

  1. 【MySQL】浅谈 varchar(N)
  2. SGU 149 树形DP Computer Network
  3. Knockout v3.4.0 中文版教程-1-入门和安装
  4. 紫书第五章训练3 D - Throwing cards away I
  5. 九度oj 题目1111:单词替换
  6. oracle create directory
  7. 使用Unity做2.5D游戏教程(二)
  8. 使用Apriori算法进行关联分析
  9. NOIP一系列模拟赛小结
  10. spring之生命周期