如果有人能够确认我是否正确地解决了以下问题,或者是否存在其他解决方案,我将非常感激。
我的应用程序会将一张大图(例如800*1720像素)加载到内存中,并在滚动视图中显示它。这张图片是一个博物馆的平面图,我想要一个简单的地图体验,可以进行滚动和缩放。在旧设备上,该图片可以成功加载,但在三星Galaxy S3上会导致内存不足错误。
通过查看LogCat消息,发现在创建位图时,分配了22MB的内存用于位图,而不是800*1720*4 = 5.5MB所需的内存。实际上,比其他设备多分配了4倍的内存,将内存使用量推超过50MB堆大小。
这个问题的推荐解决方案是使用BitmapFactory.Options.inSampleSize
选项来减少加载图片时的分辨率,从而使其需要更少的内存。然而,这会降低图像质量,而我实际上想以原始质量的全尺寸显示它,因为在旧设备上效果很好。
经过长时间的思考,我得出结论,问题在于S3的WXGA屏幕的像素密度为2.0,因此对于图像中的每个像素,位图实际上会分配4个像素。通过一些试错,我发现可以通过设置options.inScaled = false;
来防止这种情况发生。
http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inScaled
同时,我也意识到,通过使用较低的颜色深度(每个像素只用2个而不是4个)来设置options.inPreferredConfig = Bitmap.Config.RGB_565;
,我可以将内存使用减少一半到2.7MB。对于我的平面图来说,这并未影响可见的图片质量。
最终代码如下:
String uri = "drawable/floorplan";
int imageResource = getResources().getIdentifier(uri, null, getPackageName());
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inScaled = false;
Bitmap bm = BitmapFactory.decodeResource(getResources(), imageResource, options);
IVfloorplan.setImageBitmap(bm);
当显示这个位图时,您需要将其缩放回去。要计算缩放比例,您可以从以下内容中获取像素密度:
float density = getResources().getDisplayMetrics().density;
我将位图的内存使用量从22MB减少到2.7MB,在50MB堆中这是相当显著的。