问题现象:
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]
找到以上代码后,也就分析出了问题重现的方式
问题结论:
1.使用AsyncTask的时候要谨慎使用Looper
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]
找到以上代码后,也就分析出了问题重现的方式
问题结论:
1.使用AsyncTask的时候要谨慎使用Looper