Android 开发OOM解决方案
OOM(Out Of Memory)在加载图片过多或者过大的情况下会发生OOM,可以查看APP最高可用内存:
int maxMemory = (int) (Runtim.getRuntime().maxMemory()/1024);
OOM问题如何解决?
解决方案:
1、使用强引用(StrongReference)、弱引用(WeakReference)、软引用(SoftReference)、虚引用(PhantomRefrence),在内存引用中做处理。
2、在内存加载图片的时候,在内存中处理图片(边界压缩等)。
3、动态回收内存。
4、优化Dalvik的堆内存分配。
5、自定义堆内存的大小。
下面是对以上几点的详细描述:
1、引用的处理。
Heap中的对象有强可及、软可及、弱可及、虚可及和不可达对象。应用的强弱顺序是强、软、弱、虚。对于对象属于哪种可及对象,由它的最强引用决定。
String abc = new String("abc"); // 建立强引用,内存中abc是强可及,不能释放内存。
SoftReference<String> abcSoftRef = new SoftReference<String>(abc);// 建立软引用,仍然是强可及,不能释放内存。
WeakReference<String> abcWeakRef = new WeakPeference<String>(abc);//建立弱引用,强可及,不能释放内存。
abc = null;// 强引用取消,变成软可及
abcSoftRef.clear();//软引用取消,变成弱可及
总结:
强引用:只能释放没有强引用指向的内存。http://i.cnblogs.com/EditPosts.aspx?postid=5543041
弱引用:当Dalvik内存不足时,可以释放引用指向的内存。
软引用:无条件的执行Dalvik的指令。
虚引用:和以上引用不一样,跟踪引用的释放过程。
2、图片处理
BitmapFactory提供了多个方法decodeFile()解析SD卡中的图片、decodeResource()解析资源文件图片、decodeStream()解析网络图片。
2.1 单一图片压缩
public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth,int repHeight){
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if(height > reqHeight || width > reqWidth){
final int heightRatio = Math.round((float) height/(float) reqHeight);
final int widthRatio = Math.round((float) width/(float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
public static Bitmap decodeSampleBitmapFromResource(Resource res, int resId,int reqWidth,int reqHeight){
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
options.inSampleSize = calculateInSampleSize(options,reqWidth,reqHeight);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res,resId,options);
}
使用方式:
imageView.setImageBitmap(decodeSampleBitmapFromResouce(getResource(),R.id.myimg,100,100));
压缩流程:
(1)、创建Options对象,将inJustDecodeBounds设置为true.
(2)、解析图片,将属性值赋予options对象。
(3)、计算压缩比例,将比例值赋予options的inSampleSize属性。
(4)、将inJustDecodeBounds赋值false后,重新解析图片,返回Bitmap对象。
2.2 批量图片处理
处理单个照片的如上比较简单,但是一旦遇到批量图片处理,android为我们提供一个类LruCache,用于图片缓存(是一种内存缓存技术)。当缓存图片的数量到达预计设定的值的时候,近期使用比较少的图片会被回收掉。
流程:
private LruCache<String, Bitmap> mMemoryCache;
private void initLurCache(){
//1.设置缓存图片使用的内存大小,程序内存的八分之一。
int cacheMemory = (int) (Runtime.getRuntime().maxMemory()/8);
//2.初始化LruCache实例对象,重写sizeOf()、entryRemoved()方法。
mMemoryCache = new LruCache<String, Bitmap>(cacheMemory){
//必须重写此方法,来测量Bitmap的大小
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes() * value.getHeight();
}
@Override
protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {
// TODO Auto-generated method stub
super.entryRemoved(evicted, key, oldValue, newValue);
removeBitmapCache(key);
}
};
}
//3.分别实现清空缓存、添加图片到缓存、获取图片、从缓存移除图片
public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
if (getBitmapFromMemCache(key) == null && bitmap != null) {
mMemoryCache.put(key, bitmap);
}
}
public Bitmap getBitmapFromMemCache(String key) {
return mMemoryCache.get(key);
}
public void clearCache(){
if (mMemoryCache != null && mMemoryCache.size() > 0) {
mMemoryCache.evictAll();
}
}
public void removeBitmapCache(String key){
if (key != null && mMemoryCache != null) {
Bitmap bitmap = mMemoryCache.remove(key);
if (bitmap!=null) {
bitmap.recycle();
}
}
}
3、动态回收内存
显示调用recycle()方法让GC回收内存。
if(!abc.isRecycled()){
abc.recycle();
}
4、优化Dalvik堆内存分配
使用Dalvik.System.VMRuntime类提供的setTargetHeapUtilization()方法可以增强程序堆内存的处理效率。
private final static float HEAP_UTILIZATION = 0.75f;
//在onCreate()的时候调用
Runtime.getRuntime().setTargetHeapUtilization(HEAP_UTILIZATION);
5、自定义内存
private final static int HEAP_SIZE = 6*1024*1024;
Runtime.getRuntime().setMinimumHeapSize(HEAP_SIZE);
Android 开发OOM解决方案的更多相关文章
- 64位ubuntu搭建android开发环境问题解决方案
安装32位库支持,删除eclipse 的配置文件和.android目录(测试环境ubuntu 14.04) sudo apt-get install libc6-i386 lib32stdc++6 l ...
- Android OOM 解决方案
Out of Memory(内存溢出) 几乎是每个Android程序员都会遇到的事.在网上也能找到一大堆的解决方案,之前写过一篇<Android 内存溢出管理与测试>的博文.但感觉写得不是 ...
- Android开发笔记——图片缓存、手势及OOM分析
把图片缓存.手势及OOM三个主题放在一起,是因为在Android应用开发过程中,这三个问题经常是联系在一起的.首先,预览大图需要支持手势缩放,旋转,平移等操作:其次,图片在本地需要进行缓存,避免频繁访 ...
- Android开发——常见的内存泄漏以及解决方案(一)
0. 前言 转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52333954 Android的内存泄漏是Android开发领域永恒的 ...
- android 帧动画的实现及图片过多时OOM解决方案(一)
一,animation_list.xml中静态配置帧动画的顺序,如下: <?xml version="1.0" encoding="utf-8"?> ...
- Android开发——Android M(6.0) 权限解决方案
Android开发--Android M(6.0) 权限解决方案 自从Android M(6.0)发布以来,权限管理相比以前有了很大的改变,很多程序员发现之前运行的好好的Android应用在Andro ...
- Android开发——View滑动冲突解决方案
0. 前言 我们在Android开发--事件分发机制详解中深入学习了事件分发机制,为我们解决Android开发中的滑动冲突问题做了初步准备.针对滑动冲突这里给出两种解决方案:外部拦截法和内部拦截法 ...
- Android开发——常见的内存泄漏以及解决方案(二)
)Android2.3以后,SoftReference不再可靠.垃圾回收期更容易回收它,不再是内存不足时才回收软引用.那么缓存机制便失去了意义.Google官方建议使用LruCache作为缓存的集合类 ...
- 9种常见的Android开发错误及解决方案
整理总结了9个Android开发中的错误以及解决方案,共同探讨进步! 1. 如果你的项目的R文件不见的话,可以试下改版本号在保存,R文件不见一般都是布局文本出错导致. 2. 布局文件不可以有大写字母 ...
随机推荐
- jquery-进度条
function process_bar(s_date, e_date, data) { $('.modal-body').text('你选择的时期范围是:' + s_date + '到' + e_d ...
- c++多线程编程——初探
c++多线程并发可以帮助我们挖掘CPU的性能,在我们的思想中,似乎程序都是顺序执行的.这样的结论是建立在:程序是单线程程序.(比如我们平时写的hello world程序). 但是如果程序是多线程的.那 ...
- Dom中的一些接口
节点都是单个对象,有时需要一种数据结构,能够容纳多个节点.DOM 提供两种节点集合,用于容纳多个节点:NodeList和HTMLCollection.这两种集合都属于接口规范.许多 DOM 属性和方法 ...
- javascript当中onload用法
7)onload onload就是等页面加载完后才执行. 例 3.7.1 <HEAD> <meta http-equiv="content-type" conte ...
- super().__init__()方法
class first(object): def __init__(self,age,name): self.age = age self.name = name class second(first ...
- 关于Java8中的Comparator那些事
在前面一篇博文中,对于java中的排序方法进行比较和具体剖析,主要是针对 Comparator接口和 Comparable接口,无论是哪种方式,都需要实现这个接口,并且重写里面的 方法.Java8中对 ...
- 牛客寒假6-F十字阵列
链接:https://ac.nowcoder.com/acm/problem/201986来源:牛客网 题目描述 小 Q 新学会了一种魔法,可以对一个 N行M列 的网格上的敌人造成伤害 第 i 次使用 ...
- js面向对象怎么理解
js面向对象怎么理解 <一>. 认识对象.首先要认识对象:在编程中,对象(object)是具体的某一个实例,唯一的某一个个体.如:电脑就是一个统称,而你面前的这一台电脑就是对象.而电脑的统 ...
- 深入浅出Mybatis系列七-mapper映射文件配置之insert、update、delete
注:本文转载自南轲梦 注:博主 Chloneda:个人博客 | 博客园 | Github | Gitee | 知乎 上篇文章<深入浅出Mybatis系列(六)---objectFactory.p ...
- NumPy迭代数组
numpy.nditer是NumPy的一个迭代器对象,提供能够灵活的访问一个或者多个属猪元素的方式. # 迭代 z=np.arange(6).reshape(3,2) for x in np.ndit ...