【问题标题】:AsyncTask: Only the original thread that created a view hierarchy can touch its views. ( android.view.ViewRootImpl$CalledFromWrongThreadException:)AsyncTask:只有创建视图层次结构的原始线程才能接触其视图。 ( android.view.ViewRootImpl$CalledFromWrongThreadException :)
【发布时间】:2015-11-23 13:17:42
【问题描述】:

我正在我的项目中实现一个 AsyncTask。 onPrexecute 显示对话框,但应用程序崩溃并出现错误。

java.lang.RuntimeException: An error occured while executing doInBackground()
Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

这是我的 AsycTask 任务代码

private class CheckTypesTask extends AsyncTask<Void, Void, Void>{
             ProgressDialog asyncDialog = new ProgressDialog(MainActivity.this);
             String typeStatus;


             @Override
             protected void onPreExecute() {
                 //set message of the dialog
                 asyncDialog.setMessage("Please wait");
                 //show dialog
                 asyncDialog.show();
                 super.onPreExecute();
             }

             @Override
             protected Void doInBackground(Void... arg0) {

                 onPhotoTaken(); 

                return null;
             }

             @Override
             protected void onPostExecute(Void result) {

                 //hide the dialog
                 asyncDialog.dismiss();
                 asyncDialog = null;
                 super.onPostExecute(result);
             }

     }

经过研究,我将代码修改为这个

@Override
             protected Void doInBackground(Void... arg0) {
                 runOnUiThread(new Runnable() {

                        @Override
                        public void run() {
                            onPhotoTaken();     
                        }
                    });
                return null;
             }

编辑: 这是onPhoto拍摄方法

public void onPhotoTaken() {

        _taken = true;

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 4;

        Bitmap bitmap = BitmapFactory.decodeFile(_path, options);

        try {
            //ProgressDialog dialog = ProgressDialog.show(this, "Loading", "Please wait...", true);
            ExifInterface exif = new ExifInterface(_path);
            int exifOrientation = exif.getAttributeInt(
                    ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);

            Log.v(TAG, "Orient: " + exifOrientation);

            int rotate = 0;

            switch (exifOrientation) {
            case ExifInterface.ORIENTATION_ROTATE_90:
                rotate = 90;
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                rotate = 180;
                break;
            case ExifInterface.ORIENTATION_ROTATE_270:
                rotate = 270;
                break;
            }

            Log.v(TAG, "Rotation: " + rotate);

            if (rotate != 0) {

                // Getting width & height of the given image.
                int w = bitmap.getWidth();
                int h = bitmap.getHeight();

                // Setting pre rotate
                Matrix mtx = new Matrix();
                mtx.preRotate(rotate);

                // Rotating Bitmap
                bitmap = Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, false);


            }

            // Convert to ARGB_8888, required by tess
            bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
            //dialog.dismiss();

        } catch (IOException e) {
            Log.e(TAG, "Couldn't correct orientation: " + e.toString());
        }
        _image.setImageBitmap(bitmap);

此时它运行良好,但我的代码显示一个空白屏幕。 感谢期待

【问题讨论】:

  • 这取决于onPhotoTaken 方法内部的操作。显示来自onPhotoTaken 方法的代码
  • 所有与 UI 的交互都应从“onPostExecute”、“onPreExecute”或“onProgressUpdate”方法调用。此方法在 UI 线程中运行。请出示您的“onPhotoTaken”方法
  • @ρяσѕρєяK 检查我的编辑

标签: android multithreading android-asynctask


【解决方案1】:

在 doInBackground 中创建位图。

@Override
protected Bitmap doInBackground(Void... arg0) {
    return onPhotoTaken(); 
}

...

public Bitmap onPhotoTaken() {
    ....
    return bitmap;
}

并在 onPostExecute 中执行 UI 任务:

@Override 
protected void onPostExecute(Bitmap result){
    ...
    _image.setImageBitmap(result);
}

也将AsyncTask&lt;Void, Void, Void&gt; 更改为AsyncTask&lt;Void, Void, Bitmap&gt;

【讨论】:

  • @Override protected Bitmap doInBackground(Void... arg0) { return onPhotoTaken(); }
  • 返回类型与AsyncTask不兼容.doInBackground(Void[])
  • 将 AsyncTask 改为 AsyncTask
  • 是的。我已经这样做了,现在我有一个泄漏的窗口异常
  • 请问这个位图参数在哪里声明... _image.setImageBitmap(bitmap);
【解决方案2】:

您可以尝试使用 Handler 使用 new Handler(Looper.getMainLooper()); 创建它

使用它来运行任务,这将是对您的方法的调用。

【讨论】:

    【解决方案3】:

    您必须在 onPostExecute 方法上使用 _image.setImageBitmap(bitmap);

    onPostExecute 在 UI 线程上运行。

    根据经验永远不要main(UI) 线程之外修改 Views。

    【讨论】:

      【解决方案4】:

      试试这个(让你的 onPhotoTaken 返回一个位图而不是设置它):

      private class CheckTypesTask extends AsyncTask<Void, Void, Bitmap>{
               ProgressDialog asyncDialog = new ProgressDialog(MainActivity.this);
               String typeStatus;
      
      
               @Override
               protected void onPreExecute() {
                   //set message of the dialog
                   asyncDialog.setMessage("Please wait");
                   //show dialog
                   asyncDialog.show();
                   super.onPreExecute();
               }
      
               @Override
               protected Bitmap doInBackground(Void... arg0) {
                  return onPhotoTaken();
               }
      
               @Override
               protected void onPostExecute(Bitmap result) {
      
                   //hide the dialog
                   asyncDialog.dismiss();
                   asyncDialog = null;
      
                   if (result != null) {
                        _image.setImageBitmap(result);
                   }
      
                   super.onPostExecute(result);
               }
      
       }
      

      因此,您的 doInBackground 函数会返回位图,而不是将其应用于图像。 onPostExecute 在 UI 线程中运行,您可以毫无问题地操作 UI 元素,如 Imageview。

      【讨论】:

      • 很像我的回答。请注意,他还必须更改 onPhotoTaken 才能返回位图。
      • 请问这个位图参数在哪里声明... _image.setImageBitmap(bitmap);
      • @JnG 我编辑了我的答案。您必须使用结果而不是位图。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-17
      • 1970-01-01
      相关资源
      最近更新 更多