【问题标题】:Android error "Only the original thread that created a view hierarchy can touch its views"Android 错误“只有创建视图层次结构的原始线程才能触摸其视图”
【发布时间】:2017-07-15 05:09:42
【问题描述】:

我有一个AsyncTask 和一个ProgressDialog 来显示进度。问题是我无法设置ProgressDialog Max 值,直到doInBackground 方法(我需要做一些计算),我无法在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 中这样做,因为runOnUiThread 是Activity 的方法:

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

有什么想法吗? 谢谢。

【问题讨论】:

  • 在OnProgressUpdate方法上显示进度对话框
  • 你从哪里得到 myValue1?似乎您只是在任务开始后立即调用它,但没有指示从哪里检索值
  • 我正在为Network Request 分页,所以在doInBackground 方法之前我不知道有多少requests。我想在progressDialog.setMax() 方法中显示的是request 的数字
  • 也许你误解了我的意思,或者你发布的代码不完整。您在任务中做的第一件事是设置最大值,因此您必须在开始任务之前获得该值。只需在执行 AsyncTask 之前设置它
  • 我可以知道否决票的原因吗?

标签: android multithreading android-asynctask progressdialog


【解决方案1】:

你可以得到主线程的Handler并把它贴在下面

@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()相同

【讨论】:

  • 非常感谢,这正是我想要的 :)
【解决方案2】:

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

@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]);
}

【讨论】:

    【解决方案3】:

    选项 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);
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-17
      • 1970-01-01
      • 2015-05-22
      • 1970-01-01
      • 1970-01-01
      • 2013-06-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多