2016-08-24 70 views
-1

我尝试使用获取OutOfMemory异常的位图加载我的UI。我以前使用过PNG,然后将它们转换为GIF,希望通过加载位图来减少内存使用量。图像总数为291kb(使用PNG时约为2.2mb)。通过位图加载UI时发生OutOfMemory异常

我使用使用inSampleSize如果图像是比屏幕尺寸大很多加载图像的代码:

public void loadViewImage(View view, int drawableID) { 
     BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inJustDecodeBounds = true; 
     BitmapFactory.decodeResource(getResources(), drawableID, options); 
     options.inSampleSize = calculateInSampleSize(options, view.getWidth(), view.getHeight()); 
     options.inJustDecodeBounds = false; 
     view.setBackgroundDrawable(new BitmapDrawable(BitmapFactory.decodeResource(getResources(), drawableID, options))); 
} 

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; 

    while (height/inSampleSize > reqHeight || width/inSampleSize > 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; 
} 

的图像然后被加载通过:

final RelativeLayout backgroundLayout = (RelativeLayout)findViewById(R.id.backgroundLayout); 
backgroundLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { 
     @Override 
     public void onLayoutChange(View v, int left, int top, int right, int bottom, 
            int oldLeft, int oldTop, int oldRight, int oldBottom) { 
      loadViewImage(backgroundLayout, R.drawable.background); 
     } 
    }); 

此应用适用于三星Galaxy S7 Edge,但不适用于LG G2。当使用inSampleSize 2它,但我想知道这些291kb图像如何使用这么多的内存。

任何帮助,非常感谢。

+0

首先有更简单的方法来做这个使用'毕加索'为android或如果你仍然想要你自己的方式得到它使用所有沉重的逻辑来位图缩放和计算远离UI线程线索'AsyncTask ' –

+0

* 291kb images * no,当它们作为位图加载时,它们没有采用这样的大小...... **文件大小并不重要** – Selvin

+2

'图像总数为291kb'。更有意义的是图像的分辨率。由于内存使用位图取决于分辨率。现在,如果您使用BitmapFactory.decodeResource()作为位图将适用于screan,则您无法控制分辨率。你可以更好地从一个正常的输入流解码。 – greenapps

回答

0

人们告诉你尺寸无关紧要。文件大小无关紧要。 GIF vs JPG也不比PNG。重要的是以像素为单位的图像大小。位图对象是未压缩的,而文件是压缩的。这意味着每个像素需要4个字节(加上一些小的可以忽略的开销)。所以1440x2560的图像大约是370万像素,大约15MB。每个人都会占用那么多的记忆。缩放需要更多 - 你必须解码至少一部分原件来缩放它(这可能会占用两个单独尺寸的总和)。

通常,当您看到OOM错误时,问题是如何在整个代码中使用内存,而不仅仅是在一个地方。最好的方法来检查是通过堆分析寻找逃跑对象创建/保留。尽管非常大的图像(例如来自新设备上常见的12兆像素相机的图片)可能会在缩放中导致很多问题,但单独的图像需要50MB。除非你加载了大量的全屏图像,否则这应该不成问题。如果是的话,你应该在手工完成时回收它们。如果你有很多这样的布局的活动,并且可能有很深的堆栈,你可能要考虑摆脱onPause中的图像并在onResume中重新加载以节省内存。