最近做新闻客户端的时候在加载ListView的大图时会发生内存溢出的问题。内存溢出(OOM)。为了便于理解,我们不妨打个比方。缓冲区溢出好比是将十磅的糖放进一个只能装五磅的容器里。一旦该容器放满了,余下的部分就溢出在柜台和地板上,弄得一团糟。由于计算机程序的编写者写了一些编码,但是这些编码没有对目的区域或缓冲区——五磅的容器——做适当的检查,看它们是否够大,能否完全装入新的内容——十磅的糖,结果可能造成缓冲区溢出的产生。如果打算被放进新地方的数据不适合,溢得到处都是,该数据也会制造很多麻烦。但是,如果缓冲区仅仅溢出,这只是一个问题。到此时为止,它还没有破坏性。当糖溢出时,柜台被盖住。可以把糖擦掉或用吸尘器吸走,还柜台本来面貌。与之相对的是,当缓冲区溢出时,过剩的信息覆盖的是计算机内存中以前的内容。除非这些被覆盖的内容被保存或能够恢复,否则就会永远丢失。
首先想到的是三级缓存,从服务器下载下来的图片经过网络缓存,但是这种方法不优先加载, 速度慢,浪费流量。然后是本地缓存,次优先加载, 速度快;最后最好的是内存缓存,优先加载, 速度最快。我们都知道Android默认给每个app只分配16M的内存,所以用软引用 SoftReference 在内存不够时,垃圾回收器会考虑回收。但是在安卓2.3+,系统会优先将SoftReference的对象提前回收掉, 即使内存够用。所以谷歌官方建议用LruCache。least recentlly use 最少最近使用算法
会将内存控制在一定的大小内, 超出最大值时会自动回收, 这个最大值开发者自己定。其实LruCache就是用了很多的HashMap,三百多行的代码。
~~~
/**
* 内存缓存
*/
public class MemoryCacheUtils {
// private HashMap<String, SoftReference<Bitmap>> mMemoryCache = new
// HashMap<String, SoftReference<Bitmap>>();
private LruCache<String, Bitmap> mMemoryCache;
public MemoryCacheUtils() {
long maxMemory = Runtime.getRuntime().maxMemory() / 8;// 模拟器默认是16M
mMemoryCache = new LruCache<String, Bitmap>((int) maxMemory) {
@Override
protected int sizeOf(String key, Bitmap value) {
int byteCount = value.getRowBytes() * value.getHeight();// 获取图片占用内存大小
return byteCount;
}
};
}
/**
* 从内存读
*
* @param url
*/
public Bitmap getBitmapFromMemory(String url) {
// SoftReference<Bitmap> softReference = mMemoryCache.get(url);
// if (softReference != null) {
// Bitmap bitmap = softReference.get();
// return bitmap;
// }
return mMemoryCache.get(url);
}
/**
* 写内存
*
* @param url
* @param bitmap
*/
public void setBitmapToMemory(String url, Bitmap bitmap) {
// SoftReference<Bitmap> softReference = new
// SoftReference<Bitmap>(bitmap);
// mMemoryCache.put(url, softReference);
mMemoryCache.put(url, bitmap);
}
}
~~~
~~~
java中的引用
- 强引用 垃圾回收器不会回收, java默认引用都是强引用
- 软引用 SoftReference 在内存不够时,垃圾回收器会考虑回收
- 弱引用 WeakReference 在内存不够时,垃圾回收器会优先回收
- 虚引用 PhantomReference 在内存不够时,垃圾回收器最优先回收
~~~
~~~
</pre><pre name="code" class="java">为进一步优化,我们还可以考虑图片压缩技术:
~~~
~~~
//图片压缩处理
BitmapFactory.Options option = new BitmapFactory.Options();
option.inSampleSize = 2;//宽高都压缩为原来的二分之一, 此参数需要根据图片要展示的大小来确定
option.inPreferredConfig = Bitmap.Config.RGB_565;//设置图片格式
~~~
当然,如果我们用BitmapUtils也是可以的。
- 前言
- 内存溢出的解决方案
- 安卓消息推送解决方案
- 语言识别和聊天机器人的实现
- 抽屉效果的实现(DrawerLayout和SlidingMenu的对比)
- 植物大战僵尸经典开发步骤
- 屏幕适配全攻略
- 安卓图像处理入门教程
- android开发常用工具箱
- java基础知识总结
- 剖析软件外包项目
- java基础知识——网络编程、IO流
- 安卓性能优化手册
- 电商活动中刮刮卡的实现
- Android系统的安全设计与架构
- AsnycTask的内部的实现机制
- Android应用UI设计流程
- 数据结构与算法,每日一道
- html5全解析
- 深入解读XML解析
- 新闻客户端案例开发
- 细说Http协议
- win10+ubuntu双系统安装方案
- 随机验证码实现案例
- 动态数组的实现案例
- 猜拳游戏案例
- 商业级项目——基金客户端的架构设计与开发(上)