我使用eclipse开发一款Android游戏,我有很多的资源和它的图像,使用SDP大小单位大小的图像,并期待罚款,所有设备:机器人 - 堆大小错误
另外毕加索图书馆将图像加载到图像上,
主要问题是,在某些设备中,我得到堆外大小内存错误。
问题是,我是否必须在子文件夹中为ldpi,mdpi等声明不同大小的不同图像...即使我使用Sdp和Picasso?
我使用eclipse开发一款Android游戏,我有很多的资源和它的图像,使用SDP大小单位大小的图像,并期待罚款,所有设备:机器人 - 堆大小错误
另外毕加索图书馆将图像加载到图像上,
主要问题是,在某些设备中,我得到堆外大小内存错误。
问题是,我是否必须在子文件夹中为ldpi,mdpi等声明不同大小的不同图像...即使我使用Sdp和Picasso?
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。这是可以调整的,你可以在编译源代码的时候设置参数。