我是Android的新手! 我的Android SDK有一些很大的问题,因为我正在开发一个使用巨大位图(> 1200 * 1000)的应用程序,问题是在应用程序中我需要多个相同大小的图层/位图(其中3-5个) )。问题是内存堆在其中一个分配上被非常快速地消耗,并且触发了OutOfMemory异常。
好的部分是我不需要同时使用所有位图。
我尝试使用recycle()方法调用,虽然我知道它已经过时了,因为位图的内存现在驻留在堆上,而不是在本机内存上。 我还尝试从特定位图中删除所有引用,甚至手动调用System.gc()但没有用,无法删除位图。 好吧,也许会有内存泄漏我不知道,虽然我对此表示怀疑。
我尝试了各种各样的解决方案,但都没有。
对我来说最好的选择是重用一个位图,但BitmapFactory的解码方法只知道分配一个消耗内存的新Bitmap。
我的问题是,你知道一种重用位图像素的方法(覆盖位图的像素而不分配另一个位图/像素数组)可以用于Android ???问题是我无法驻留在GarbageCollector解决方案上,因为当我必须确定那些位图从内存中移除/其他位图不会被分配时,我的应用程序中有特定的时刻。
另一个解决方案是:你知道一种直接在SD卡上绘制一些位图的方法,而不通过堆内存吗?当我尝试分配一个大位图(原始大小的两倍)来连接两个其他处理过的位图时,它崩溃了...这就是我要问的原因。是否有可能直接从数据流中实例化Canvas r其他绘图对象?
其他解决方案是使用类似虚拟交换内存的东西,它可以模拟堆内存,但可以在SDCARD上进行缓存。但也找不到这样做的方法。
答案 0 :(得分:2)
编写一个单独的类来执行自定义位图操作:
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
class BitmapLoader
{
public static int getScale(int originalWidth,int originalHeight,
final int requiredWidth,final int requiredHeight)
{
//a scale of 1 means the original dimensions
//of the image are maintained
int scale=1;
//calculate scale only if the height or width of
//the image exceeds the required value.
if((originalWidth>requiredWidth) || (originalHeight>requiredHeight))
{
//calculate scale with respect to
//the smaller dimension
if(originalWidth<originalHeight)
scale=Math.round((float)originalWidth/requiredWidth);
else
scale=Math.round((float)originalHeight/requiredHeight);
}
return scale;
}
public static BitmapFactory.Options getOptions(String filePath,
int requiredWidth,int requiredHeight)
{
BitmapFactory.Options options=new BitmapFactory.Options();
//setting inJustDecodeBounds to true
//ensures that we are able to measure
//the dimensions of the image,without
//actually allocating it memory
options.inJustDecodeBounds=true;
//decode the file for measurement
BitmapFactory.decodeFile(filePath,options);
//obtain the inSampleSize for loading a
//scaled down version of the image.
//options.outWidth and options.outHeight
//are the measured dimensions of the
//original image
options.inSampleSize=getScale(options.outWidth,
options.outHeight, requiredWidth, requiredHeight);
//set inJustDecodeBounds to false again
//so that we can now actually allocate the
//bitmap some memory
options.inJustDecodeBounds=false;
return options;
}
public static Bitmap loadBitmap(String filePath,
int requiredWidth,int requiredHeight){
BitmapFactory.Options options= getOptions(filePath,
requiredWidth, requiredHeight);
return BitmapFactory.decodeFile(filePath,options);
}
}
然后,从您的活动中,调用此类的Bitmap reqBitmap = loadBitmap(String filePath,int requiredWidth,int requiredHeight)
方法,提供从sd卡获取的位图的filepath
,并将requiredWidth和requiredHeight设置为您希望将位图缩放到的尺寸。现在使用reqBitmap
。
这样,大型位图在加载到堆内存之前将按比例缩小。我有同样的问题,这解决了我。 :)
答案 1 :(得分:1)
我遇到过类似的问题,recycle()
对我不起作用。所以我做了一些像集myBitmap = null
那样微不足道的事情。这向垃圾收集器指示myBitmap已被解除引用并且不再需要它。因此它将完成释放堆的工作。然后,您可以继续使用myBitmap加载新的位图,而不会出现内存异常。
答案 2 :(得分:0)
这可能为时已晚,但我建议使用“BitmapFactory.Options.inBitmap”。如果设置,skia将尝试重新使用此位图来解码图像。 http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inBitmap