android - 堆大小错误

时间:2016-08-24 03:34:27

标签: android eclipse

我使用eclipse开发了一款Android游戏,我有很多资源和图像,使用sdp size单位来调整图像大小并在所有设备中都很好看:

https://github.com/intuit/sdp

Picasso Library也可以在imageviews上加载图片,

主要问题是在某些设备中我出现了堆积大小内存错误。

问题是,我是否必须在子文件夹中为ldpi,mdpi等声明不同大​​小的不同图像...即使我使用的是Sdp和Picasso?

1 个答案:

答案 0 :(得分:0)

Android在加载大背景或大量图片时,往往会导致内存溢出(Out of Memory Error),根据我处理过这些问题和其他开发人员经验的经验,整理解决方案如下(部分内容代码和文本源无法验证):

选项一,提醒注意阅读图像的方法,适当的压缩 尽量不要使用或者setImageResource设置setImageBitmap BitmapFactory.decodeResource或者设置一个大图像,因为这些函数在完成解码后,最终要通过createBitmap java层来完成,需要消耗更多的内存。 相反,使用BitmapFactory.decodeStream的第一个方法,创建一个位图,然后将它设置为ImageView的源码,decodeStream最大的秘密就在于它直接调用JNI>> nativeDecodeAsset()完成解码,不再需要使用createBitmap java层,从而节省空间java层。

    InputStream is = this.getResources () openRawResource (R.drawable.pic1).;

    BitmapFactory.Options options = new BitmapFactory.Options ();

    options.inJustDecodeBounds = false;

    options.inSampleSize = 10; // width, hight to a tenth of the original

    Bitmap btp = BitmapFactory.decodeStream (is, null, options);

如果我们在读取时添加Config参数图像,它可以有效地减少内存负载,从而有效防止抛出内存异常。

/ **

 * In most provinces memory reads local resources image

 * @param Context

 * @param ResId

 * @return

 * /

public static Bitmap readBitMap (Context context, int resId) {

    BitmapFactory.Options opt = new BitmapFactory.Options ();

    opt.inPreferredConfig = Bitmap.Config.RGB_565;

    opt.inPurgeable = true;

    opt.inInputShareable = true;

    // Get the resource image

    . InputStream is = context.getResources () openRawResource (resId);

    return BitmapFactory.decodeStream (is, null, opt);

    }
另外,decodeStream拍照直接读取字节码,不能根据机器的各种分辨率自动适应,然后使用decodeStream,需要hdpi和mdpi,ldpi配置相应的图像资源,或者在不同的分辨率下机器都是相同的尺寸(像素数),显示的尺寸不正确。

选项二,适当时及时恢复内存映像 通常,当您可以释放资源时onStop / onDestroy图片中的Activity或Fragment:

if(imageView!= null&& imageView.getDrawable()!= null){

  Bitmap oldBitmap = ((BitmapDrawable) imageView.getDrawable ()) getBitmap ().;

  imageView.setImageDrawable (null);

  if (oldBitmap! = null) {

        oldBitmap.recycle ();

        oldBitmap = null;

  }

}

//其他代码。

System.gc();

在释放资源后,需要注意相关Drawable Bitmap的释放或是否有对其他类的引用。如果正常调用,可以通过Bitmap.isRecycled()方法判断是否有明显的恢复;如果它与UI线程接口相关的代码使用,您需要小心避免可能的资源回收使用,否则您可能会抛出系统异常: E / AndroidRuntime:java.lang.IllegalArgumentException:无法绘制回收的位图 并且无法有效捕获和处理异常。

选项三,加载完整图像时避免不必要 只需要知道图像大小的情况下,就无法将图像加载到内存中。 图像压缩使用BitmapFactory时,BitmapFactory.Options在设置为true后的inJustDecodeBounds中,然后使用decodeFile()等方法,可以在不分配空间的状态下计算图片的大小。例如:

BitmapFactory.Options opts = new BitmapFactory.Options();

//设置为true inJustDecodeBounds

opts.inJustDecodeBounds = true;

//使用decodeFile获取的图像宽度和高度

BitmapFactory.decodeFile(path,opts);

//打印出图片的宽度和高度

Log.d("示例",opts.outWidth +"," + opts.outHeight); (Ps:实际上,基本图像信息的图像读取的标题信息的原理)

选项IV,优化了Dalvik VM堆内存分配 堆(HEAP)大部分是VM内存,通常是动态分配的。堆大小不是静态的,通常有一种分配机制来控制它的大小。例如,初始HEAP是4M大,当4M空间占用超过75%的时候,重新分配堆是8M大;当8M占用超过75%时,分配的堆大16M。倒挂时,当16M堆使用不到30%时,其尺寸减小8M大。重置堆大小,特别是在压缩时,通常与内存复制有关,因此更改堆大小会对效率产生不利影响。 堆利用率堆利用率。当实际利用率偏离此时,虚拟内存堆大小要在GC中调整时间,所以实际占用率要缩小一个百分点。 setTargetHeapUtilization方法dalvik.system.VMRuntime类可以提供增强的处理效率程序堆内存。

private final static float TARGET_HEAP_UTILIZATION = 0.75f;

//程序可以调用onCreate

VMRuntime.getRuntime()setTargetHeapUtilization(TARGET_HEAP_UTILIZATION)。;

程序V,自定义堆(堆)内存大小 对于一些Android项目,影响性能的瓶颈主要是Android自身的内存管理问题,目前手机厂商更吝啬RAM对于软件流畅性非常敏感,对RAM性能的影响,除了优化的Dalvik VM堆内存外赋值,我们也可以定义自己的软件来强制内存大小,我们使用dalvik.system.VMRuntime类提供Dalvik来设置最小堆内存,例如:

private final static int CWJ_HEAP_SIZE = 6 * 1024 * 1024;

VMRuntime.getRuntime()setMinimumHeapSize(CWJ_HEAP_SIZE);. //设置最小堆内存大小为6MB。

但是,上面的方法仍然是一个问题,实际上只是更改函数setMinimumHeapSize堆的下限,它防止堆内存分配过于频繁,当设置最小堆大小超过上限(Max Heap Size)时虽然仍然使用堆栈限制,但由于内存不足无效。

最后,请告诉我们图片占用内存算法的过程。 android中的基类图像处理是Bitmap,顾名思义,是一个位图。内存密集型算法,例如:图像宽度*高度*配置。 如果Config设置为ARGB_8888,则上述配置为4. 480 * 320图像内存使用量为480 * 320 * 4字节。 默认情况下android内存占用的过程为16M,因为Bitmap除了持有java数据外,底层的C ++图形库都会保存一个skia SKBitmap对象,因此一般建议内存的图像大小不应超过8M。这可以调整,您可以在编译源代码时设置参数。