Android 异步任务OnProgressUpdate CalledFromErrorThreadException:只有创建视图层次结构的原始线程才能接触其视图
我正在使用AsyncTask下载一个数据库,其中有一个progressdialog,显示UI上的进度。我的一些用户收到错误信息: CalledFromErrorThreadException:只有创建视图层次结构的原始线程才能接触其视图 据我所知,只有当您试图在UI线程之外更新视图时,才会发生这种情况。以下是错误: com…updateops.DbCreate.onProgressUpdate(DbCreate.java:70) 在com…updateops.DbCreate.onProgressUpdate(DbCreate.java:1) 这是我的代码:Android 异步任务OnProgressUpdate CalledFromErrorThreadException:只有创建视图层次结构的原始线程才能接触其视图,android,multithreading,android-asynctask,Android,Multithreading,Android Asynctask,我正在使用AsyncTask下载一个数据库,其中有一个progressdialog,显示UI上的进度。我的一些用户收到错误信息: CalledFromErrorThreadException:只有创建视图层次结构的原始线程才能接触其视图 据我所知,只有当您试图在UI线程之外更新视图时,才会发生这种情况。以下是错误: com…updateops.DbCreate.onProgressUpdate(DbCreate.java:70) 在com…updateops.DbCreate.onProgres
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);
}
公共类DbCreate扩展异步任务{
私有静态上下文mCtx;
私有静态进程对话框mDialog;
公共静态AmazonSimpleDBClient mSDbClient;
公共静态AmazonS3客户端MS3客户端;
私有静态int-mAppVersion;
私有静态布尔mCreate;
公共DbCreate(上下文ctx、int-versionCode、布尔创建){
mCtx=ctx.getApplicationContext();
mAppVersion=版本代码;
mDialog=新进度对话框(ctx);
mDialog.setProgressStyle(ProgressDialog.STYLE_水平);
setMessage(“正在检查服务器访问。请稍候…”);
mDialog.setCancelable(假);
mDialog.setMax(1);
mDialog.show();
mCreate=create;
}
受保护的void onProgressUpdate(字符串…名称){
如果(名称[0]。等于(“项”)){
mDialog.incrementProgressBy(1);
}else if(名称[0].equals(“setMax”)){
mDialog.setProgress(0);
mDialog.setMax(Integer.parseInt(名称[1]);根据调用publishProgress(进度…)后在UI线程上调用onProgressUpdate(进度…)
您应该分析整个日志报告,以检查异步任务是否有可能是在其他线程上创建的
如果你真的找不到根本原因,你可以使用在UI线程上创建的处理程序来解决问题。你的代码看起来很好,在大多数情况下它应该可以工作。我建议你使用处理程序。你可以在UI线程中编写处理程序,并从onProgressUpdate()调用它。这将完全确保UI工作在UI线程中完成
这肯定会解决您的问题,但我不知道您第一手为什么会出错。我以前见过这种问题,但从未找到具体的原因。我遇到了与您描述的相同的问题,我通过对AsyncTask所拥有的上下文使用runOnUiThread()
调用来解决它(如您在示例中所示)
以下解决方案应该可以解决您的问题
@Override
protected void onProgressUpdate(final String... messages){
myActivityReference.runOnUiThread(new Runnable() {
@Override
public void run() {
// Your UI changes here.
}
});
}
值得注意的是,我的AsyncTask
最初是从AlertDialog
中调用的,我认为这就是问题的根源。我在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
上执行,HandlerThread本质上是一个带有自定义循环器的工作线程。因此,这就是崩溃发生的原因
因此,在您的情况下,AsyncTask
的内部处理程序很可能绑定到与工作线程(如HandlerThread
)相关联的非主循环器,而onUpdateProgress
则在工作线程上处理
我发现这个bug在Android 2.3设备上随处可见。因此,我检查了2.3中AsyncTask
的源代码,发现:
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设备上表现正常。正如错误所说,您不能触摸(更改/更新)任何视图(控件:如按钮、编辑文本等)超出主线程。我不确定,但也许您应该尝试:mCtx.mDialog.setMax(Integer.parseInt(name[1]));如果这是必需的,那么这段代码将永远不会工作。这是一份崩溃报告,我正在试图找到影响一小部分用户的根本原因和解决方案。可能是,您不是从UI线程调用此异步。我是从UI线程调用此异步。它只在一个位置调用。处理程序解决方案有效。我仍然不确定e发生这种情况的原因(仅在部分手机/OS版本上发生)。我只能在运行2.3.3的N1上复制它,但开发人员控制台中也有报告。处理程序解决方案有效,但我必须将它交给Robin,因为它已在较早时发布。尽管我从未发现问题……这也解决了我的问题,只不过我只是运行了rununuithread(new Runnable()…
没有活动引用。