Android 错误 "Only the original thread that created a view hierarchy can touch its views"

Android error "Only the original thread that created a view hierarchy can touch its views"

我有一个 AsyncTask 和一个 ProgressDialog 来显示进度。问题是我在doInBackground方法之前无法设置ProgressDialog Max值(我需要做一些计算),我无法在onPreExecute方法中设置它,因为我不知道该值还。

我收到此错误是因为显然我正在尝试从背景 Thread.

修改 UI

Only the original thread that created a view hierarchy can touch its views. 我在 AsyncTask 构造函数中初始化 ProgressDialog

public MyAsyncTask(Context context) {
    this.context = context;

    progressDialog = new ProgressDialog(context);
    progressDialog.setTitle(context.getString(R.string.wait_for_sync_title));
    progressDialog.setMessage(context.getString(R.string.please_wait));
    progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    progressDialog.setIndeterminate(true);
    progressDialog.setCancelable(false);
}

我在onPreExecute方法中显示:

@Override
protected void onPreExecute() {
    super.onPreExecute();
    progressDialog.show();
}

我需要更新 doInBackground 方法中的 ProgressDialog:

@Override
protected void doInBackground() {
    progressDialog.setMax(myValue1);
    progressDialog.setIndeterminate(false);
    publishProgress(myValue2);
}

这里是onProgressUpdate方法:

 @Override
protected void onProgressUpdate(Integer... values) {
    super.onProgressUpdate(values);
    progressDialog.setProgress(values[0]);
}

最后,我在 onPostExecute 方法中将其关闭:

@Override
protected void onPostExecute(Void void) {
    if(progressDialog != null) {
       progressDialog.dismiss();
    }
}

我已经在 thread 方法中尝试过,但我不能在 AsyncTask 中这样做,因为 runOnUiThreadActivity 的一种方法:

runOnUiThread(new Runnable() {
   @Override
   public void run() {
      progressDialog.setMax(myValue1);
      progressDialog.setIndeterminate(false);
   }
});

有什么想法吗? 谢谢。

我建议简单地让你的进度值是一对可以代表当前和最大进度的整数

@Override
protected void doInBackground() {
    publishProgress(myValue2, myValue1);
}

@Override
protected void onProgressUpdate(Integer... values) {
    super.onProgressUpdate(values);
    if (progressDialog.isIndeterminate()) { //optional check
        progressDialog.setMax(values[1]);
        progressDialog.setIndeterminate(false);
    }
    progressDialog.setProgress(values[0]);
}

选项 1

从 progressDialog 获取上下文,将其转换为 Activity 并使用 runOnUiThread :

((Activity)progressDialog.getContext()).runOnUiThread(new Runnable() {
            @Override
            public void run() {
                progressDialog.setMax(myValue1);
                progressDialog.setIndeterminate(false);
            }
        });

选项 2:

配置 onProgressUpdate 以设置最大值并在 doInBackground 中使用适当的值配置调用 publishProgress :

 @Override
    protected Void doInBackground(Void... voids) {
        // use this to set max
        publishProgress(null, maxValue);

        // use this to update progress
        publishProgress(progress);

        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);

        final Integer progressValue = values[0];

        if (progressValue == null) {
            // set max
            final Integer maxValue = values[1];
            progressDialog.setMax(maxValue);
            progressDialog.setIndeterminate(false);
        } else {
            // update progress
            progressDialog.setProgress(progressValue);
        }
    }

您可以获取主线程的 Handler 和 post 如下所示

@Override protected Void doInBackground(Void... params) {
  new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override public void run() {
      progressDialog.setMax(myValue1);
      progressDialog.setIndeterminate(false);
    }
  });
  publishProgress(myValue2);
}

以上方法同调用runOnUiTHread()