如何在不发生内存溢出异常的情况下获取相对于屏幕大小缩放的位图

3
在我的活动中,我正在创建一个与设备分辨率(宽度和高度)相同的位图。
我所做的是:

Bitmap mBitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888);

其中screenWidth和screenHeight是:
    screenHeight = displaymetrics.heightPixels;
    screenWidth = displaymetrics.widthPixels;

现在,如果我创建这个位图,我的堆会增加到19mb,这不是很好。
所以告诉我两件事:
1. 以最小内存消耗的方式创建与屏幕宽度和高度相对应的位图是什么?
2. 使用后如何销毁位图?
请给我一些源代码或源代码链接。

你可能想要查看这个视频 https://www.youtube.com/watch?v=HY9aaXHx8yA - Luis Pereira
1
通过阅读开发者网站,我确切地理解了这一点,但我想要根据我的需求得到解决方案,我想要获得屏幕尺寸的位图,同时它应该是最小尺寸。 - Coas Mckey
你可以通过调用 destroyDrawingCache() 方法来销毁位图。例如:iv.destroyDrawingCache() 或 frame.destroyDrawingCache()。这里的 iv 和 frame 分别是 ImageView 和 FrameLayout。 - Nitesh
1个回答

3
  1. 如何以最小的内存消耗创建与屏幕宽度和高度相对应的位图?

    1. 绝不要使用屏幕高度或宽度创建Bitmap,因为这会基于设备的密度非常庞大。相反,使用屏幕的高度宽度来计算纵横比。现在将高度固定为一个常量值(如1200px),然后根据纵横比计算宽度ImageView或任何其他视图将正确缩放此项。
    2. 如果您真的想要透明度,则使用Bitmap.Config.ARGB_8888,如果不需要,则可以使用RGB_565或列表中的其他内容:http://developer.android.com/reference/android/graphics/Bitmap.Config.html
    3. 如果您不是创建新的bitmap,而是从某个资源解码bitmap,则请遵循以下几点:
      1. 您需要使用BitmapFactory.Options.inSampleSize来减少采样。那么如果您已经知道高度和宽度,如何计算inSampleSize?请参阅此处:http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
      2. 所以您做了所有这些事情,但是inSampleSize仍然不够高,您会遇到OutOfMemoryError?别担心,如果是这种情况,请在其中catchOutOfMemoryError并增加您的inSampleSize,然后再次进行位图解码。将此逻辑放入循环中,因此永远不会崩溃。

  2. 使用完位图后如何销毁它?

    1. 这真的很简单。确保调用Bitmap.recycle()方法。并删除对位图的所有引用。一旦这样做,资源将被释放,GC将进行清理。

更新:当您使用screen_widthscreen_height创建位图时,您将得到一个巨大的位图。相反,创建一个适合整个屏幕的低分辨率位图。您可以查看以下代码,了解如何执行此操作。

    float screenHeight = displaymetrics.heightPixels;
    float screenWidth = displaymetrics.widthPixels;

    float aspectRatio  = screenWidth/screenHeight;

    int modifiedScreenHeight = 1000;
    int modifiedScreenWidth = (int) (modifiedScreenHeight * aspectRatio);

    Bitmap mBitmap = Bitmap.createBitmap(modifiedScreenWidth, modifiedScreenHeight, Bitmap.Config.ARGB_8888);

现在您已经获得了具有正确纵横比的位图。您可以将此位图直接用于ImageView以填充整个屏幕。请确保在ImageView中使用android:scaleType="fitXY"


我想制作一个位图,它可以扩展到屏幕的宽度和高度。你有什么建议吗?请用代码解释一下。谢谢! - Coas Mckey
这里的1000并不是屏幕高度,而是图像的分辨率。你需要根据你负担得起的内存选择该值。我相信1200像素宽或高的图像在所有手机上看起来都很好。 - Henry
最后一个问题,降低修改后的屏幕高度会降低位图大小和堆中的大小吗?还是会增加? - Coas Mckey
1000 在所有手机上都会很好看。如果你要用平板电脑,那么可以再高一点。这完全取决于 screenWidthscreenHeight。我通常会将 modifiedSceenWidth 计算为 min(screenWidth/2, 1000)。你选择的 modifiedScreenHeight 值越低,图像质量就越低,但堆大小就会更小。如果你不在意质量,那就使用 1000 或更少。 - Henry
不行,你不能这样做。创建意味着内存分配,因此你需要按正确的大小进行创建。 - Henry
显示剩余14条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接