您的位置:首页 > 移动开发 > Android开发

Handle收不到消息的问题分析

2016-12-26 08:44 501 查看
说到Handler,今天遇到一个问题:就是handler 发送了消息,却在handleMessage的地方没有收到消息,甚是奇怪。代码如下:

[java] view
plain copy

 





//创建一个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

 





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

 





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

 





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

 





/** 

 * 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

 





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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  handler android
相关文章推荐