Handle收不到消息的问题分析
2016-12-26 08:44
501 查看
说到Handler,今天遇到一个问题:就是handler 发送了消息,却在handleMessage的地方没有收到消息,甚是奇怪。代码如下:
[java] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
//创建一个Thread,使得 handler 在子线程中执行耗时操作,而不是在主线程中执行。
HandlerThread handlerThread = new HandlerThread("handler_thread");
handlerThread.start();
// 创建一个Handler 用前面创建的 handlerThread.getLooper()
mHandler = new Handler(handlerThread.getLooper());
以上代码,是多么正常的实例化mHandler;然后通过 mHandler.sendEmptyMessage(0); 发送一个消息出去,这是又多么简单的一次操作。可结果却是多么的出人意料。因为同样的代码,同样的操作,可程序在某些情况下,却收不到了消息?!无奈,只能去分析下源码,看看为什么没有收到消息?!
问题根因跟踪分析:
1、当我们调用 sendEmptyMessage()方法的时候,最终会调用到 Handler.enqueueMessage 方法
[java] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
2、然后跟踪到 MessageQueue.enqueueMessage方法。
[java] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
final boolean enqueueMessage(Message msg, long when) {
........
boolean needWake;
synchronized (this) {
// 此处会判断 是否消息队列已经退出,如果退出返回false。
if (mQuiting) {
RuntimeException e = new RuntimeException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
return false;
}
................
}
}
if (needWake) {
nativeWake(mPtr);
}
return true;
}
3、那么mQuitting 什么情况会赋值 true呢?跟踪代码找到如下代码:
[java] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
final void quit() {
if (!mQuitAllowed) {
throw new RuntimeException("Main thread not allowed to quit.");
}
synchronized (this) {
if (mQuiting) {
return;
}
mQuiting = true;
}
nativeWake(mPtr);
}
由此可见,当调用 quit的时候会对mQuiting进行赋值true,这样在以后的发送消息的时候,就不会添加到消息队列当中去了。
而官方的sendEmptyMessage定义也证明了这一点。
[java] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
/**
* Sends a Message containing only the what value.
*
* @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.
(通常情况下不会返回false,除非消息队列被强制退出了)
*/
public final boolean sendEmptyMessage(int what)
{
return sendEmptyMessageDelayed(what, 0);
总结:
通过上面分析,问题的原因就有可能是不合法的调用了 quit方法,搜索项目,发现有些地方,在某些情况下会不和业务逻辑的去执行 quit方法,导致无法处理的消息。再就是可能的一个原因,就是 HandlerThread可能会系统强制回收了。
所以,为了安全,我们在调用 发送消息的时候最好做一个判断,如果消息发送不成功则重新创建handler。代码如下:
[java] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/9e12f1d3e499fc949c886e7c9e0484f9)
private void createHandler(){
HandlerThread handlerThread = new HandlerThread("handler_thread");
handlerThread.start();
mHandler = new Handler(handlerThread.getLooper());
}
private void sendMessage(int what){
boolean isOk = mHandler.sendEmptyMessage(what);
if (!isOk){
//创建创建handler
createHandler();
isOk = mHandler.sendEmptyMessage(what);
}
}
原文地址:http://blog.csdn.net/ilygjl/article/details/51137346
[java] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
//创建一个Thread,使得 handler 在子线程中执行耗时操作,而不是在主线程中执行。
HandlerThread handlerThread = new HandlerThread("handler_thread");
handlerThread.start();
// 创建一个Handler 用前面创建的 handlerThread.getLooper()
mHandler = new Handler(handlerThread.getLooper());
以上代码,是多么正常的实例化mHandler;然后通过 mHandler.sendEmptyMessage(0); 发送一个消息出去,这是又多么简单的一次操作。可结果却是多么的出人意料。因为同样的代码,同样的操作,可程序在某些情况下,却收不到了消息?!无奈,只能去分析下源码,看看为什么没有收到消息?!
问题根因跟踪分析:
1、当我们调用 sendEmptyMessage()方法的时候,最终会调用到 Handler.enqueueMessage 方法
[java] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
2、然后跟踪到 MessageQueue.enqueueMessage方法。
[java] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
final boolean enqueueMessage(Message msg, long when) {
........
boolean needWake;
synchronized (this) {
// 此处会判断 是否消息队列已经退出,如果退出返回false。
if (mQuiting) {
RuntimeException e = new RuntimeException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
return false;
}
................
}
}
if (needWake) {
nativeWake(mPtr);
}
return true;
}
3、那么mQuitting 什么情况会赋值 true呢?跟踪代码找到如下代码:
[java] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
final void quit() {
if (!mQuitAllowed) {
throw new RuntimeException("Main thread not allowed to quit.");
}
synchronized (this) {
if (mQuiting) {
return;
}
mQuiting = true;
}
nativeWake(mPtr);
}
由此可见,当调用 quit的时候会对mQuiting进行赋值true,这样在以后的发送消息的时候,就不会添加到消息队列当中去了。
而官方的sendEmptyMessage定义也证明了这一点。
[java] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
/**
* Sends a Message containing only the what value.
*
* @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.
(通常情况下不会返回false,除非消息队列被强制退出了)
*/
public final boolean sendEmptyMessage(int what)
{
return sendEmptyMessageDelayed(what, 0);
总结:
通过上面分析,问题的原因就有可能是不合法的调用了 quit方法,搜索项目,发现有些地方,在某些情况下会不和业务逻辑的去执行 quit方法,导致无法处理的消息。再就是可能的一个原因,就是 HandlerThread可能会系统强制回收了。
所以,为了安全,我们在调用 发送消息的时候最好做一个判断,如果消息发送不成功则重新创建handler。代码如下:
[java] view
plain copy
![](https://oscdn.geek-share.com/Uploads/Images/Content/201611/a7c8e286f463007e2a900848b93dd72c.png)
private void createHandler(){
HandlerThread handlerThread = new HandlerThread("handler_thread");
handlerThread.start();
mHandler = new Handler(handlerThread.getLooper());
}
private void sendMessage(int what){
boolean isOk = mHandler.sendEmptyMessage(what);
if (!isOk){
//创建创建handler
createHandler();
isOk = mHandler.sendEmptyMessage(what);
}
}
原文地址:http://blog.csdn.net/ilygjl/article/details/51137346
相关文章推荐
- 技术记录---Handle收不到消息的问题分析
- ActiveMQ5.3的接收不到消息的问题
- DllMain中不当操作导致死锁问题的分析——线程中调用GetModuleFileName、GetModuleHandle等导致死锁
- 百度云推送消息到达率低问题定位分析
- 百度云推送消息到达率低问题定位分析
- 个推延迟收到消息问题原因分析
- 基于WEB服务器导致消息中心各组件之间无法正常工作的问题分析与解决
- android异步处理,分析Handle消息机制
- 解决Win7系统下以管理员身份运行的程序接收不到拖放文件消息[WM_DROPFILES]问题的方法
- EventBus收不到消息问题【原创】
- 关于百度云、极光的推送的问题,为什么控制台发送消息成功,而手机端接收不到消息
- ActiveMQ5.3的接收不到消息的问题
- mina客户端发送消息延迟问题分析
- 基于mina服务器框架在android客户端接中文收不到消息以及发送不出中文的的问题
- [转载]DllMain中不当操作导致死锁问题的分析——线程中调用GetModuleFileName、GetModuleHandle等导致死锁
- 关于 微信发送被动回复音乐消息 用户接收不到的问题
- Activemqcpp 在接收设置了TTL的消息时候,出现receive timeout接收不到消息的问题
- 通过Intent传输图片导致广播消息异常的问题根因分析(通过分析Android源码反向推理)
- 关于小周同志在消息模块定位功能修改时存在的问题分析
- 信息异步处理,关于handle和thread交互信息,只能更改一个textview的问题原因分析