为什么即使使用Google的实现,Bitmap加载仍然很慢?

时间:2017-01-29 16:49:57

标签: android multithreading performance bitmap imageview

我使用这两个功能,稍微修改了Android docs中Google的代码,以使用文件路径:

public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) >= reqHeight
                && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

public static Bitmap decodeSampledBitmapFromFilePath(String pathName, int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(pathName, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeFile(pathName, options);
}

这个想法是使用缩小版的Bitmap映射到ImageView而不是完整的东西,这是浪费。

mImageView.setImageBitmap(decodeSampledBitmapFromFilePath(pathToFile, 100, 100));

我实现了一个按下按钮然后旋转到下一个图像的东西,但与我的模拟器相比,我的手机上还有一个显着的延迟(ImageView需要花费一些时间来填充)。然后偶尔我的手机应用程序会崩溃,我无法在我的模拟器上复制它。

我上面发布的这段代码有问题吗?我使用代码的方式有问题吗?

示例:

public void reloadPic() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            final Bitmap bm = decodeSampledBitmapFromFilePath(filepath, mImageViewWidth, mImageViewHeight);
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mImageView.setImageBitmap(bm);
                }
            });
        }
    }).start();
}

1 个答案:

答案 0 :(得分:1)

您的代码在线程之间跳转了好几次。首先你启动一个线程。然后你等待它被安排你在该线程上解码。然后将命令发布到UI线程并等待它被安排。然后你将一个绘图命令发布到ui线程(这是setImageBitmap所做的一部分)。然后你必须处理第一个进来的任何其他命令。然后你实际绘制屏幕。实际上只有3种方法可以加快速度:

1)摆脱线程。您不应该在UI线程上解码大量图像,但解码1也不错。

2)以正确的尺寸存储图像。这可能意味着提前创建图像的缩略图。那你就不需要扩展了。

3)预加载图像。如果只有一个按钮并且您知道它将加载什么图像,请在需要之前加载它,因此当按下按钮时您已准备就绪。浪费了一点记忆,但只有1张图片值得。 (如果你有很多可能的下一张图片,这不是一个可行的解决方案。)