Asynctask onPostExecute未执行的问题分析

问题现象:
app使用Asynctask从网络下载数据,并将数据同步更新到UI上进行显示。
在app使用的过程中,偶尔会出现数据未更新的情况,且这个问题现象一时找不到必现的操作方法
跟踪问题原因发现是AsyncTask.onPostExecute未被执行到的原因。

问题解决办法:
google之后,发现可以通过如下方法解决问题:
在app的application中的onCreate方法中增加如下代码
[mw_shl_code=java,true]try {
                        Class.forName("android.os.AsyncTask");
                } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                }[/mw_shl_code]

问题的解决办法可以查看如下链接的一些说明:
1.http://code.google.com/p/android/issues/detail?id=20915
2.http://stackoverflow.com/questions/4280330/onpostexecute-not-being-called-in-asynctask-handler-runtime-exception

问题原因:
AsyncTask有如下代码:

[mw_shl_code=java,true]private static final InternalHandler sHandler = new InternalHandler();[/mw_shl_code]

此处的InternalHandler extends Handler,且使用默认的构造函数。
看Handler的默认构造函数如下:

[mw_shl_code=java,true]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;
    }[/mw_shl_code]

问题原因的关键分析点在于

mLooper = Looper.myLooper();

也就是说,使用Handler使用默认的构造函数的话,Handler使用的Looper是Looper中如下函数返回的内容:

[mw_shl_code=java,true]public static final Looper myLooper() {
        return (Looper)sThreadLocal.get();
    }[/mw_shl_code]
以上种种,可以查看依次查看AsyncTask-->>Handler-->>Looper-->>TreadLocal的源代码自行理解。
在以上内容分析完毕后,搜索app中AsyncTask的使用场景,发现在不同的使用场景中,有一处场景在使用AsyncTask之前有如下代码

[mw_shl_code=java,true]Looper myLooper = Looper.myLooper();
                            if (myLooper == null) {

Looper.prepare();
                            }[/mw_shl_code]
找到以上代码后,也就分析出了问题重现的方式

时间: 2024-08-10 19:22:50

Asynctask onPostExecute未执行的问题分析的相关文章

Android查缺补漏(线程篇)-- AsyncTask的使用及原理详细分析

本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8515304.html 一.AsyncTask的使用 AsyncTask是一种轻量级的异步任务类,可以很方便的在线程池中执行异步任务,并且将进度和结果传递给主线程.其底层由Thread+handler实现. AsyncTask是一个抽象的泛型类,其类的声明如下: public abstract class AsyncTask<Params, Progress, Result>

Erlang的gen_server的terminate()/2未执行

官方资料参考: Module:terminate(Reason, State) Types: Reason = normal | shutdown | {shutdown,term()} | term() State = term() This function is called by a gen_server when it is about to terminate. It should be the opposite of Module:init/1 and do any necessa

Android中AsyncTask基本用法与源码分析(API 23)

原文链接 http://sparkyuan.github.io/2016/03/23/AsyncTask源码剖析(API 23)/ 转载请注明出处 Android的UI是线程不安全的,想在子线程中更新UI就必须使用Android的异步操作机制,直接在主线程中更新UI会导致程序崩溃. Android的异步操作主要有两种,AsyncTask和Handler.AsyncTask是一个轻量的异步类,简单.可控.本文主要结合API 23的源码讲解一下AsyncTask到底是什么. 基本用法 声明:Andr

【MS SQL】通过执行计划来分析SQL性能

如何知道一句SQL语句的执行效率呢,只知道下面3种: 1.通过SQL语句执行时磁盘的活动量(IO)信息来分析:SET STATISTICS IO ON (开启) / SET STATISTICS IO OFF (关闭) 2.通过SQL语句执行时语法分析.编译以及执行所消耗的时间:SET STATISTICS TIME ON (开启) / SET STATISTICS TIME OFF (关闭) 3.通过执行计划查看:Ctrl + L -------------------------------

一个多线程问题引发的血案-(代码段执行完毕,子进程未执行完毕导致段错误)

今天遇到一个问题,gdb执行程序完全没有问题,但直接执行就会段错误,百思不得其解,各种纠结,各种搜索引擎都试了一遍,无果!后来问题还是被我自己挖出来了. 看下边一段代码: int TaskSendControl() { pthread_t prov_thread[CLIENT_NUM]; int prov[CLIENT_NUM]; for(int i=0; i< CLIENT_NUM; i++) { prov[i] = i; if( pthread_create(&prov_thread[i

android AsyncTask的局限性 及 源码分析

参考: http://blog.csdn.net/hitlion2008/article/details/7983449 2.3之前 AsyncTask有个全局的线程池  最大的值是5 超过后只能等待执行 3.0后增加了excuteOnExcutor方法 设置自定义线程池.但是默认线程池是个顺序线程池每次只能执行一个任务且按照顺序. AsyncTask 部分源代码 . public abstract class AsyncTask<Params, Progress, Result> { pri

jQuery清除、停止队列中剩下(未执行的函数)

<!DOCTYPE html><html><head> <meta charset="utf-8"> <title>jQuery清除.停止队列中剩下(未执行的函数)</title> <script src="http://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js"> </script> <scrip

重置已分配未执行的任务(300,400-》200)

初始动作:重置所有已分配未执行的任务 1.删除/ZkTest/tasks/* 2.修改所有已分配未执行的任务记录 节点挂掉:监控父节点(/ZkTest/nodes)会感知,系统删除节点,回调通知程序 1.遍历修改子节点下的所有已分配未执行的任务记录 /ZkTest/tasks/${NodeKey}/TaskInst*** 2.修改对应的数据库记录 节点重连:节点重连回调会捕捉后修改zkNodekey(old->new) 1.遍历处理老zkNodeKey下的所有已分配未执行的任务记录 /ZkTes

ElasticSearch远程任意代码执行漏洞(CVE-2014-3120)分析

原理 这个漏洞实际上非常简单,ElasticSearch有脚本执行(scripting)的功能,可以很方便地对查询出来的数据再加工处理. ElasticSearch用的脚本引擎是MVEL,这个引擎没有做任何的防护,或者沙盒包装,所以直接可以执行任意代码. 而在ElasticSearch里,默认配置是打开动态脚本功能的,因此用户可以直接通过http请求,执行任意代码. 其实官方是清楚这个漏洞的,在文档里有说明: First, you should not run Elasticsearch as