即使我使用异步线程(滞后UI),主线程也做太多工作

时间:2014-12-14 14:25:09

标签: java android multithreading android-asynctask

我有一个应用程序,用户可以从他们的图库中选择一张图片。

它会将图片放在ImageView框中,并且有几个EditText字段需要填写。

选择照片后,打开键盘需要几秒钟,显示文字输入等几秒钟。

我在AsyncTask中进行所有图形操作等,如下所示:

调用AsyncTask:

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode,  data);
    if(resultCode == RESULT_OK) {
        try {

            new SetPathAsync(data.getData()).execute();

        }catch (Exception e){
            Log.e("Error", "Error with setting the image. See stack trace.");
            e.printStackTrace();
        }
    }
}

完成任务:

公共类SetPathAsync扩展了AsyncTask {

    Uri uri;

    // override this to set uri for bitmap
    public SetPathAsync(Uri uriPass){
        super();
        uri = uriPass;
    }

    @Override
    protected Boolean doInBackground(String... params) {

        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = getContentResolver().query(uri, projection, null, null, null);

        cursor.moveToFirst();
        filePath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
        cursor.close();

        // Convert file path into bitmap image using below line.

        bitmap = BitmapFactory.decodeFile(filePath);

        filePathForUpload = filePath;

        Log.i("Test", filePath);

        try {
            ExifInterface exif = new ExifInterface(filePath);
            int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
            bitmap = rotateBitmap(bitmap, orientation);
        }catch (Exception e) {
            Log.d("Error", "error with bitmap!");
            e.printStackTrace();
        }
        return null;
    }

    public Bitmap rotateBitmap(Bitmap bitmap, int orientation) {
        Matrix matrix = new Matrix();
        switch (orientation) {
            case ExifInterface.ORIENTATION_NORMAL:
                return bitmap;
            case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
                matrix.setScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                matrix.setRotate(180);
                break;
            case ExifInterface.ORIENTATION_FLIP_VERTICAL:
                matrix.setRotate(180);
                matrix.postScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_TRANSPOSE:
                matrix.setRotate(90);
                matrix.postScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_90:
                matrix.setRotate(90);
                break;
            case ExifInterface.ORIENTATION_TRANSVERSE:
                matrix.setRotate(-90);
                matrix.postScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_270:
                matrix.setRotate(-90);
                break;
            default:
                return bitmap;
        }

        Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        bitmap.recycle();
        return bmRotated;
    }


    @Override
    protected void onPostExecute(Boolean aBoolean) {
        super.onPostExecute(aBoolean);

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                imageView.setImageBitmap(bitmap);
                button.setEnabled(false);
            }
        });
    }
}

代码中的其他所有内容都只是普通的UI任务。

为什么在Async线程中仍然存在滞后的原因?

2 个答案:

答案 0 :(得分:1)

不明显。你必须对它进行分析。

此外,无需在SetPathAsync构造函数中调用super(),也不需要runOnUiThread - onPostExecute已在UI线程上运行。

答案 1 :(得分:1)

这是因为位图的大小非常大,以至于应用程序完全没有内存,这意味着即使认为它是在新线程上完成的,仍然没有足够的内存来运行其他指令。

当我在logcat中遇到错误时,我注意到了这一点,例如:Grow heap (frag case)

为了解决这个问题,我按比例缩小了图像:

BitmapFactory.Options bmpOpts = new BitmapFactory.Options();
bmpOpts.inSampleSize = 3;

bitmap = BitmapFactory.decodeFile(filePath, bmpOpts);

现在它运行顺利!