我正在使用AsyncTask下载一个数据库,其中包含一个显示UI进度的progressdialog。我的一些用户收到错误:
CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触及其视图。
据我所知,只有在尝试从UI线程更新Views时才会发生这种情况。这是错误:
... COM updateops.DbCreate.onProgressUpdate(DbCreate.java:70) 在com ... updateops.DbCreate.onProgressUpdate(DbCreate.java:1)
这是我的代码:
public class DbCreate extends AsyncTask<String, String, String>{
private static Context mCtx;
private static ProgressDialog mDialog;
public static AmazonSimpleDBClient mSDbClient;
public static AmazonS3Client mS3Client;
private static int mAppVersion;
private static boolean mCreate;
public DbCreate(Context ctx, int versionCode, boolean create) {
mCtx = ctx.getApplicationContext();
mAppVersion = versionCode;
mDialog = new ProgressDialog(ctx);
mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mDialog.setMessage("Checking for server access. Please wait...");
mDialog.setCancelable(false);
mDialog.setMax(1);
mDialog.show();
mCreate = create;
}
protected void onProgressUpdate(String... name) {
if (name[0].equals("item")) {
mDialog.incrementProgressBy(1);
} else if (name[0].equals("setMax")) {
mDialog.setProgress(0);
mDialog.setMax(Integer.parseInt(name[1])); <-- This is line 70
}}
@Override
protected String doInBackground(String... arg0) {
**do stuff**
publishProgress("setMax", ""+ 3);
}
在我看来,我正在遵循我应该做的事情,以避免此错误。有人知道为什么会这样吗?
编辑:我还应该提到这段代码大部分时间都有效。我在开发者控制台上收到崩溃报告。
答案 0 :(得分:5)
根据onProgressUpdate(Progress ...)在调用publishProgress(Progress ...)后在UI线程上调用。
您应该分析整个日志报告,以检查您的异步任务是否有可能在其他线程上创建。
如果你真的找不到根本原因,你可以使用在UI线程上创建的处理程序来解决。
答案 1 :(得分:1)
您的代码看起来很好,在大多数情况下它应该可以工作。我建议你使用处理程序。您可以在UI线程中编写处理程序,并从onProgressUpdate()调用它。这将完全确保UI工作在UI线程中完成。
这肯定会解决您的问题,但我不知道为什么您第一时间会遇到错误。我以前见过这种问题,从来没有得到具体的理由。
答案 2 :(得分:1)
我遇到了与您描述的问题相同的问题,我通过对AsyncTask所拥有的上下文进行runOnUiThread()
调用来修复它(正如您在示例中所做的那样)。
以下解决方案应该解决您的问题;
@Override
protected void onProgressUpdate(final String... messages){
myActivityReference.runOnUiThread(new Runnable() {
@Override
public void run() {
// Your UI changes here.
}
});
}
值得注意的是,AsyncTask
最初是在AlertDialog
内调用的,我认为这是导致问题开始的原因。
答案 3 :(得分:0)
我在Android 2.3.x设备上发现了同样的问题,这是崩溃日志:
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRoot.checkThread(ViewRoot.java:2934)
...
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.os.HandlerThread.run(HandlerThread.java:60)
日志表明onProgressUpdate
和onPostExecute
在HandlerThread
上执行,Looper
本质上是具有自定义AsyncTask
的工作线程。这就是发生崩溃的原因。
因此,在您的情况下,HandlerThread
的内部处理程序可能绑定到与onUpdateProgress
之类的工作线程关联的非主looper,而AsyncTask
则在工作线程上处理。
我发现这个bug在Android 2.3设备上普遍存在。因此,我在2.3中检查了private static final InternalHandler sHandler = new InternalHandler();
private static class InternalHandler extends Handler {
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
...
}
}
的源代码并找到了:
AsyncTask
内部处理程序可能绑定到非主循环器。
我还检查了private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
...
}
的最新源代码并看到了更改:
InternalHandler
onUpdateProgress
构造函数消除了绑定到非主要循环器的可能性,因此-|
在Android 2.3后设备上表现正常。