我使用eclipse开发了一款Android游戏,我有很多资源和图像,使用sdp size单位来调整图像大小并在所有设备中都很好看:
Picasso Library也可以在imageviews上加载图片,
主要问题是在某些设备中我出现了堆积大小内存错误。
问题是,我是否必须在子文件夹中为ldpi,mdpi等声明不同大小的不同图像...即使我使用的是Sdp和Picasso?
答案 0 :(得分:0)
选项一,提醒注意阅读图像的方法,适当的压缩 尽量不要使用或者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。这可以调整,您可以在编译源代码时设置参数。