对于安卓的内存溢出,我是找不到什么好的方法,曾经疯狂的百度过,看的文章都是大同小异,很多都是浮云,下面是我以前总结的,前些天有人问到,我自己也没解决,我翻到了自己的笔记,就是下面的,从word粘上来,大家探讨,看谁有其他解决方案可以交流下,下面是我的笔记:
大家都知道Android的上层应用是基于 Dalvik Virtual Machine的。Dalvik VM的特点是基于寄存器,相比SUN的JVM(基于堆栈,没有寄存器)来说,理论上完成同样的功能需要的指令条数少,但是指令集复杂。到了Android2.2,Dalvik终于实现了JIT(Just In Time)功能,前进了一大步。
近期 们遇到OutOfMemory的错误,通常是堆内存溢出。网上有些帖子说可以通过函数设置应用的HEAP SIZE:
大家都知道Android的上层应用是基于 Dalvik Virtual Machine的。Dalvik VM的特点是基于寄存器,相比SUN的JVM(基于堆栈,没有寄存器)来说,理论上完成同样的功能需要的指令条数少,但是指令集复杂。到了Android2.2,Dalvik终于实现了JIT(Just In Time)功能,前进了一大步。
近期 们遇到OutOfMemory的错误,通常是堆内存溢出。网上有些帖子说可以通过函数设置应用的HEAP SIZE:
private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ;
VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //设置最小heap内存为6MB大小。
用这个方法解决问题,其实是不对的。
堆(HEAP)是VM中占用内存最多的部分,通常是动态分配的。堆的大小不是一成不变的,通常有一个分配机制来控制它的大小。比如初始的HEAP是4M大,当4M的空间被占用超过75%的时候,重新分配堆为8M大;当8M被占用超过75%,分配堆为16M大。倒过来,当16M的堆利用不足30%的时候,缩减它的大小为8M大。重新设置堆的大小,尤其是压缩,一般会涉及到内存的拷贝,所以变更堆的大小对效率有不良影响。
private final
static floatTARGET_HEAP_UTILIZATION = 0.75f;
VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION);
经过我多次测试,用mVMRuntime.getTargetHeapUtilization()方法查看,程序本来的利用率就0.75f,所以这个设置不设置都一样。
因此上面的方法都没有用,网上非常多像上面方法的转载都是浮云
安卓内存的溢出主要是使用图片时的内存溢出 使用图片时怎样避免内存溢出呢?
问小华华的:
VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //设置最小heap内存为6MB大小。
用这个方法解决问题,其实是不对的。
堆(HEAP)是VM中占用内存最多的部分,通常是动态分配的。堆的大小不是一成不变的,通常有一个分配机制来控制它的大小。比如初始的HEAP是4M大,当4M的空间被占用超过75%的时候,重新分配堆为8M大;当8M被占用超过75%,分配堆为16M大。倒过来,当16M的堆利用不足30%的时候,缩减它的大小为8M大。重新设置堆的大小,尤其是压缩,一般会涉及到内存的拷贝,所以变更堆的大小对效率有不良影响。
上面只是个例子,不过可以看到三个参数:max heap size, min heap size, heap utilization(堆利用率)。Max Heap Size,是堆内存的上限值,Android的缺省值是16M(某些机型是24M),对于普通应用这是不能改的。函数setMinimumHeapSize其实只是改变了堆的下限值,它可以防止过于频繁的堆内存分配,当设置最小堆内存大小超过上限值时仍然采用堆的上限值(16M),对于内存不足没什么作用。所以说堆内存的大小无法改变,也就无法阻止内存溢出,你通过VMRuntime.getRuntime()setMinimumHeapSize只是改变了堆的下限值而已,而且VMRuntime类在android
2.3系统及以上系统已经没有了。
setTargetHeapUtilization(float newTarget) 可以设定内存利用率的百分比,当实际的利用率偏离这个百分比的时候,虚拟机会在GC的时候调整堆内存大小,让实际占用率向个百分比靠拢。
// 程序 onCreate 时调用private final
static floatTARGET_HEAP_UTILIZATION = 0.75f;
VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION);
经过我多次测试,用mVMRuntime.getTargetHeapUtilization()方法查看,程序本来的利用率就0.75f,所以这个设置不设置都一样。
因此上面的方法都没有用,网上非常多像上面方法的转载都是浮云
安卓内存的溢出主要是使用图片时的内存溢出 使用图片时怎样避免内存溢出呢?
问小华华的:
java.lang.Runtime这个类在安卓中还有用吗?它跟dalvik.system.VMRuntime类说的是同一个运行环境吗?
Runtime.getRuntime().totalMemory()
和
freeMemory()/
是否就是
Davik
虚拟机分配给
app
的大小和程序可用的内存大小
?
答:
android
下每个应用程序都会开启一个对应的
java
虚拟机
可以这样理解吧,对于内存图片导致的内存溢出确实没有什么好的解决办法,只能试着从降低图片的分辨率上去解决了
.
我的解决办法:
下面方法好像并没有损坏图片的质量。
通过下面的方法来设置Activity的背景图片:
private void setBackground() {
mBitmap = BitmapUtil.readBitMap( this , R.drawable. top123_bg );
rl_root .setBackgroundDrawable( new BitmapDrawable( mBitmap )); //rl_root 为根布局对象
}
//Activity 中的大对象手动释放,主要有 ListView 、和 ListView 的适配器,和设置为背景图片的 bitmap
@Override
rotected void onDestroy() {
leftListTurnPageUtil = rightGridTurnPageUtil = null ;
listAdapter = null ;
gridAdapter = null ;
mGridView = null ;
mListView = null ;
if (! mBitmap .isRecycled()){
mBitmap .recycle(); // 回收图片所占的内存
}
System.gc(); // 提醒系统及时回收
super .onDestroy();
}
public class BitmapUtil {
/**
* 以最省内存的方式读取本地资源的图片
* @param context
* @param resId 图片资源 id
* @return Bitmap
*/
public static Bitmap readBitMap(Context context, int resId){
BitmapFactory.Options options = new BitmapFactory.Options();
options. inPreferredConfig = Bitmap.Config. RGB_565 ;
options. inPurgeable = true ;
options. inInputShareable = true ;
InputStream is = context.getResources().openRawResource(resId); // 获取资源图片的输入流
return BitmapFactory. decodeStream (is, null , options);
}
}
下面方法好像并没有损坏图片的质量。
通过下面的方法来设置Activity的背景图片:
private Bitmap mBitmap;
/** 设置背景图片 */private void setBackground() {
mBitmap = BitmapUtil.readBitMap( this , R.drawable. top123_bg );
rl_root .setBackgroundDrawable( new BitmapDrawable( mBitmap )); //rl_root 为根布局对象
}
//Activity 中的大对象手动释放,主要有 ListView 、和 ListView 的适配器,和设置为背景图片的 bitmap
@Override
rotected void onDestroy() {
leftListTurnPageUtil = rightGridTurnPageUtil = null ;
listAdapter = null ;
gridAdapter = null ;
mGridView = null ;
mListView = null ;
if (! mBitmap .isRecycled()){
mBitmap .recycle(); // 回收图片所占的内存
}
System.gc(); // 提醒系统及时回收
super .onDestroy();
}
public class BitmapUtil {
/**
* 以最省内存的方式读取本地资源的图片
* @param context
* @param resId 图片资源 id
* @return Bitmap
*/
public static Bitmap readBitMap(Context context, int resId){
BitmapFactory.Options options = new BitmapFactory.Options();
options. inPreferredConfig = Bitmap.Config. RGB_565 ;
options. inPurgeable = true ;
options. inInputShareable = true ;
InputStream is = context.getResources().openRawResource(resId); // 获取资源图片的输入流
return BitmapFactory. decodeStream (is, null , options);
}
}
解决方案参考自:
http://blog.csdn.net/dai_zhenliang 我在这里面转载了好几篇关于图片内存溢出的,有兴趣的可以看下,仅供参考,不一定能解决问题的,我的主要参考如下:
一、用 BitmapFactory.decodeStream方法来读取图片
一、用 BitmapFactory.decodeStream方法来读取图片
尽量不要使用
setImageBitmap
或
setImageResource
或
BitmapFactory.decodeResource
来设置一张大图,因为这些函数在完成
decode
后,最终都是通过
java
层的
createBitmap
来完成的,需要消耗更多内存。因此,改用先通过
BitmapFactory.decodeStream
方法,创建出一个
bitmap
,再将其设为
ImageView
的
source
,
decodeStream
最大的秘密在于其直接调用
JNI>>nativeDecodeAsset()
来完成
decode
,无需再使用
java
层的
createBitmap
,从而节省了
java
层的空间。如果在读取时加上图片的
Config
参数,可以跟有效减少加载的内存,从而更有效阻止抛
out of Memory
异常。另外,
decodeStream
直接拿的图片来读取字节码了,
不会根据机器的各种分辨率来自动适应,
使用了
decodeStream
之后,需要在
hdpi
和
mdpi
,
ldpi
中配置相应的图片资源,
否则在不同分辨率机器上都是同样大小(像素点数量),显示出来的大小就不对了。
二、以最省内存的方式读取本地资源的图片
public static Bitmap readBitMap(Context context, int resId){
BitmapFactory.Options options =
new
BitmapFactory.Options();
options.
inPreferredConfig
= Bitmap.Config.
RGB_565
;
options.
inPurgeable
=
true
;
options.
inInputShareable
=
true
;
InputStream is = context.getResources().openRawResource(resId);
//
获取资源图片的输入流
return BitmapFactory.
decodeStream(is,
null
, options);
}
三、以减少图片宽高的方式读取图片
1.
public
static
Bitmap readBitMap2(Context context,
int
resId) {
InputStream is = context.getResources().openRawResource(resId);
BitmapFactory.Options options =
new
BitmapFactory.Options();
options.
inJustDecodeBounds
=
false
;
options.
inSampleSize
= 10;
//width
,
hight
设为原来的十分一
return BitmapFactory.
decodeStream(is,
null
,options);
}
2. if(!bmp.isRecycle() ){
bmp.recycle() // 回收图片所占的内存
system.gc()// 提醒系统及时回收
}
希望对大家有帮助,更希望有其他的解决方法的朋友们贡献一下自己的解决经验。
2. if(!bmp.isRecycle() ){
bmp.recycle() // 回收图片所占的内存
system.gc()// 提醒系统及时回收
}
希望对大家有帮助,更希望有其他的解决方法的朋友们贡献一下自己的解决经验。
http://sunhuichuan.blog.163.com/blog/static/1849445962013316115224803/