AsyncTask:只有创建视图层次结构的原始线程才能触及其视图。 (android.view.ViewRootImpl $ CalledFromWrongThreadException :)

时间:2015-11-23 13:17:43

标签: android multithreading android-asynctask

我正在我的项目中实现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;
             }

EDITTED: 这是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);

此时效果很好,但我的代码显示为空白屏幕。 在期待中感谢

2 个答案:

答案 0 :(得分:1)

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

onPostExecute在UI线程上运行。

根据经验,从不修改View帖子之外的main(UI)

答案 1 :(得分:0)

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

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线程中运行,您可以毫无问题地操作像Imageview这样的UI元素。