有效加载位图 - 仍然出现内存不足错误

时间:2016-11-03 16:38:26

标签: java android bitmap

加载自定义图片时出现内存不足错误。我阅读https://developer.android.com/training/displaying-bitmaps/load-bitmap.html寻求帮助。

我正在按照示例解码流以首先获取大小信息,然后解码。仍然在第一次解码时崩溃。有办法解决这个问题吗?

ava.lang.OutOfMemoryError:无法分配带有16776928个空闲字节的48771084字节分配和25MB直到OOM BackgroundImageManager.java,第84行

dalvik.system.VMRuntime.newNonMovableArray原生方法 2 android.graphics.BitmapFactory.nativeDecodeStream Native方法 3 android.graphics.BitmapFactory.decodeStreamInternal BitmapFactory.java,第882行 4 android.graphics.BitmapFactory.decodeStream BitmapFactory.java,第858行 5 android.graphics.BitmapFactory.decodeStream BitmapFactory.java,第896行 6 com.myapp.Utils.BackgroundImageManager.background BackgroundImageManager.java,第8行

public class BackgroundImageManager {
    private final static String TAG = BackgroundImageManager.class.getSimpleName();
    private static InputStream currentBackgroundImage;

    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;
            }
        }
        Log.v("Biscuit-Sample", String.valueOf(inSampleSize));
        if (inSampleSize < 4) {
            inSampleSize = 4;
        }
        return inSampleSize;
    }

    public static Drawable background(Context context, Store store) {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);

        String bgUri = null;
        int bgId = 0;
        if (store != null) {
            bgUri = store.backgroundImageURI;
            bgId = store.backgroundImageNumber;
        }

        if (currentBackgroundImage != null) {
            try {
                currentBackgroundImage.close();
                Log.v(TAG, "Current background image closed.");
            } catch (IOException e) {
                Log.e(TAG, "Could not close background image.", e);
            }
        }

        if(bgUri != null && !bgUri.isEmpty()) {
            try {
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = true;

                Activity activity = (Activity) context;
                Display display = activity.getWindowManager().getDefaultDisplay();
                Point size = new Point();
                display.getSize(size);
                int width = size.x;
                int height = size.y;
                BitmapFactory.decodeStream( context.getContentResolver().openInputStream(Uri.parse(bgUri)) );
                options.inSampleSize = BackgroundImageManager.calculateInSampleSize(options, width, height);
                Bitmap bitmap = BitmapFactory.decodeStream( context.getContentResolver().openInputStream(Uri.parse(bgUri)) );
                Drawable d = new BitmapDrawable(context.getResources(), bitmap);
                return d;
            } catch (FileNotFoundException e) {
                Log.e(TAG, "Custom background image file could not be found.", e);
            } catch (IOException e) {
                Log.e(TAG, "Could not close custom background image after creating drawable", e);
            }
        }
        if(bgId != 0) {
            try {
                return context.getResources().getDrawable(bgId);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return context.getResources().getDrawable(R.drawable.bg_default);
    }

2 个答案:

答案 0 :(得分:1)

要处理bitmpas,您可以使用众多可用的开源库之一。 E.g Fresco

问题:

首先,您要对相同的位图进行两次解码。

BitmapFactory.decodeStream( context.getContentResolver().openInputStream(Uri.parse(bgUri)) );
options.inSampleSize = BackgroundImageManager.calculateInSampleSize(options, width, height);
Bitmap bitmap = BitmapFactory.decodeStream( context.getContentResolver().openInputStream(Uri.parse(bgUri)) );

这可能是错误的复制/粘贴。在第一行中,位图是解码而不使用。删除第一个BitmapFactory.decodeStream

问题出在这里

Bitmap bitmap = BitmapFactory.decodeStream( context.getContentResolver().openInputStream(Uri.parse(bgUri)) );

应该是

Bitmap bitmap = BitmapFactory.decodeStream( context.getContentResolver().openInputStream(Uri.parse(bgUri)), null, options);

该选项的对象必须是该方法调用的一部分才能被使用。

答案 1 :(得分:0)

管理图像的更好方法是使用Picasso库,因为它管理缓存和内存,因此可以避免OutOfMemory崩溃。

示例:Picasso.with(Context).load("your_url").into(yourImageView);

更多信息: Picasso library