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



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

它将图片放在一个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();
        }
    }
}

执行任务:

public class SetPathAsync extensions 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 任务。

为什么它在异步线程中仍然存在滞后?

它并不明显。您必须对其进行分析。

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

这是

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

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

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

BitmapFactory.Options bmpOpts = new BitmapFactory.Options();
bmpOpts.inSampleSize = 3;
bitmap = BitmapFactory.decodeFile(filePath, bmpOpts);

现在运行顺利!

最新更新