2016-08-24 58 views
0

我使用eclipse开发一款Android游戏,我有很多的资源和它的图像,使用SDP大小单位大小的图像,并期待罚款,所有设备:机器人 - 堆大小错误

https://github.com/intuit/sdp

另外毕加索图书馆将图像加载到图像上,

主要问题是,在某些设备中,我得到堆外大小内存错误。

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

回答

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时,你可以释放资源:

如果(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:Can not绘制回收的位图 而且无法有效捕获和处理异常。

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

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

//设置为true inJustDecodeBounds

opts.inJustDecodeBounds = TRUE;

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

BitmapFactory.decodeFile(路径,选择采用);

//打印出来的画面宽度和高度

Log.d( “示例”,opts.outWidth + “” + opts.outHeight); (PS:事实上,标题信息由基本图像信息的图像读出的原理)

方案四,优化的Dalvik虚拟机的堆内存分配 堆(堆)是一个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).;

方案五,自定义堆(堆)内存大小 对于一些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,则上面的Config为4. 480 * 320图像内存使用量为480 * 320 * 4字节。 默认情况下android内存占用的进程为16M,由于他所持有的Bitmap除了java数据之外,底层的C++图形库将持有skia SKBitmap对象,因此一般建议内存的图片大小不应超过8M。这是可以调整的,你可以在编译源代码的时候设置参数。