Imageview中的Android内存不足错误

时间:2014-03-29 08:26:44

标签: android

我需要在我的应用中设置背景图片。我使用了imageview,并尝试以编程方式设置其背景。我得到'内存不足错误'。我在SO上阅读了其他帖子,并且根据屏幕的高度和宽度更改了我的代码以获取图像。我尝试过其他一些东西,但仍然会遇到同样的错误。请帮助。

感谢。

    @Override
protected void onResume() {
    super.onResume();

    ivBackground.setImageBitmap(decodeSampledBitmapFromResource(getResources(), R.drawable.themes, getDisplayWidth(), getDisplayHeight()));
    ivBackground.setScaleType(ScaleType.CENTER_CROP);
}

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
        int reqWidth, int reqHeight) {

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

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

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}



public int getDisplayHeight(){
    DisplayMetrics dm = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(dm);
    return dm.heightPixels;
}

public int getDisplayWidth(){
    DisplayMetrics dm = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(dm);
    return dm.widthPixels;
}



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;
}

xml layout

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
    <ImageView android:id="@+id/ivBackground"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"/>

    <android.support.v4.view.ViewPager

        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainPage"
         />

5 个答案:

答案 0 :(得分:2)

我没有“声望”发表评论所以发布答案。 这就是我认为正在发生的事情。 活动是第一次开始,因此imageview没有任何东西可以显示。

  • onResume将位图绑定到imageview
  • onPause活动暂停
  • OnResume现在再来一次这里很棘手。因为活动没有被破坏(我假设,你必须检查)该位图仍然绑定到imageView。当此行被称为“ivBackground.setImageBitmap”时,它将调用“decodeSampledBitmapFromResource”方法以根据屏幕大小获取位图。最终会创建一个缩小到屏幕尺寸的位图,因此在内存中加载 2 位图会花费很短的时间。当您加载全屏大小的位图时,内存中每个位图可能需要20-25 MB。因此,这可能会造成“内存不足”的情况。

解决方案:在onPause方法中设置setImageBitmap null对我有用

答案 1 :(得分:2)

我通过这样做解决了这个错误 - 在我的情况下,图像尺寸对于我的手机来说太大了所以我必须动态调整它才能将它加载到imageview中。

这就是我所做的:

第1步:

我发现了我的屏幕分辨率:How do I get the ScreenSize programmatically in android

    WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    DisplayMetrics metrics = new DisplayMetrics();
    display.getMetrics(metrics);
    int width = metrics.widthPixels;
    int height = metrics.heightPixels;

第2步:

然后我动态调整位图的大小:

    Bitmap bm = drawableToBitmap(ContextCompat.getDrawable(this, R.drawable.cloud_plane));
    Bitmap bitmapsimplesize = Bitmap.createScaledBitmap(bm, width, height, true);
    bm.recycle();
    background.setImageBitmap(bitmapsimplesize);

可以在此处找到drawableToBitmap方法:How to convert a Drawable to a Bitmap?

public static Bitmap drawableToBitmap (Drawable drawable) {
    Bitmap bitmap = null;

    if (drawable instanceof BitmapDrawable) {
        BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
        if(bitmapDrawable.getBitmap() != null) {
            return bitmapDrawable.getBitmap();
        }
    }

    if(drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
        bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
    } else {
        bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    }

    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);
    return bitmap;
}

答案 2 :(得分:1)

只需将largeHeap="true"放入应用程序代码(AndroidManifest.xml)

即可
<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:largeHeap="true"
    android:theme="@android:style/Theme.Black.NoTitleBar" >

我认为它会对你有所帮助。
谢谢你。

答案 3 :(得分:1)

在活动上添加以下代码:

  @Override
        public void onDestroy(){

                bitmap.recycle();

            System.gc();
            super.onDestroy();

        }

答案 4 :(得分:0)

我在上面的代码中添加了以下内容并使其正常工作。它或多或少与其他人在这里提到的相关。所以,感谢大家的帮助。

@Override
protected void onDestroy() {
    System.gc();
    super.onDestroy();
    ivBackground.setImageBitmap(null);
}