【软引用】弱引用 图片的加载与缓存 OOM
强引用
软引用 SoftReference
弱引用 WeakReference
软引用与OOM
软引用的使用是与【内存】挂钩的一个引用类,主要应用于内存敏感的高速缓存,其实在Android中是经常使用的到的,由于Android的虚拟机是基于寄存器的Dalvik,它的堆大小只有16M,我们都清楚无论是Android应用程序,还是Java应用程序,在实例化对象的时候都是在堆中完成的...因此在Android中这个堆的大小要求确实是很苛刻的,一旦我们读取的资源数据过大,或者是内存里的对象由于声明的周期太长,没有被及时的释放,那么就很有可能造成OOM的发生...我们都知道GC的回收机制在正常的情况下并不是时时刻刻都在工作的,它的工作时间是不定期的,因此如果在GC不工作的期间我们的内存已经爆表,那就必定导致OOM,OOM在Android是经常见到的一种情况,对象的不及时释放,static关键字的使用,线程不可控,还有最常见的就是在读取Bitmap的时候导致这种情况的发生...OOM是一个非常严重的问题,但是如果内存得不到充分的使用,这个其实也是一个潜在的问题,SoftReference(软引用),其实给我的感觉就是为了解决这样的问题,每一个对象通过软引用进行实例化,那么这个对象的数据也就会被保存起来,当需要再次调用这个对象中的数据的时候,只需要通过对象的get()方法就可以获取到该对象所保存的数据信息,其实也会是我们所说的cache,当内存快要不足的时候,GC会迅速的把所有的软引用清除掉,释放内存空间...这样不仅结合了对象的cache,同时还解决了OOM的发生,一举两得...虽然说是一举两得的东西,保证了内存能够安全的被使用,那么相反就要牺牲效率,在每一个软引用对象被实例化的时候,其实还是需要耗费许多的时间的...因此到底如何运用,取决于我们遇到的问题.在Android中,其实有一些时候还是由于Bitmap的问题导致内存不足的发生,图片相对而言还是比较大的,像素高的图片在读取的情况下是非常耗费内存的,如果读取的图片过多的话,那就更加的显而易见了,图片过多,内存会被吃的非常的紧,因此我们需要在Bitmap中去使用软引用,这样就可以避免OOM的发生...还可以有效的去使用内存...示例代码
public class MainActivity extends ListActivity {private TextView tv_info;private ImageView imageView;public static final String BIG_IMAGE_PATH = Environment.getExternalStorageDirectory().getPath() + "/big.jpg";public static final String SMALL_IMAGE_PATH = Environment.getExternalStorageDirectory().getPath() + "/small.png";private Bitmap smallBitmap;private Bitmap bigBitmap;private Bitmap weakBitmap;//定义一个HashMap,保存软引用的Bitmap对象,可防止OOMprivate Map<String, SoftReference<Bitmap>> imageCaches = Collections.synchronizedMap(new HashMap<String, SoftReference<Bitmap>>());//弱引用可以在未被GC回收之前的获取到其中的Bitmap...一旦GC将其回收,那么就获取不到这个对象中的Bitmap了。该回收的时候,GC会自动的将其回收private WeakReference<Bitmap> weakReference;protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);String[] array = { "加载压缩后的大图到内存", "加载一张6000*8000(183M)的原图到内存", //"保存Bitmap的【SoftReference】到HashMap", "获得缓存到HashMap的Bitmap对象",//"保存Bitmap的【WeakReference】到HashMap", "获得WeakReference中的Bitmap对象", };setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, new ArrayList<String>(Arrays.asList(array))));tv_info = new TextView(this);tv_info.setTextColor(Color.BLUE);tv_info.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);tv_info.setPadding(20, 10, 20, 10);getListView().addFooterView(tv_info);imageView = new ImageView(this);getListView().addFooterView(imageView);}private int clickCount;@Overrideprotected void onListItemClick(ListView l, View v, int position, long id) {clickCount++;if (clickCount % 2 == 0) {//大小图轮流显示smallBitmap = BitmapFactory.decodeFile(SMALL_IMAGE_PATH);imageView.setImageBitmap(smallBitmap);tv_info.setText(formatInfo(smallBitmap));} else {switch (position) {case 0:bigBitmap = decodeSampledBitmapFromFile(BIG_IMAGE_PATH, 1080, 1920);//每次都是重新加载的,从点击后响应速度就可以看得出来break;case 1:bigBitmap = BitmapFactory.decodeFile(BIG_IMAGE_PATH);//图片有多大就实际加载多大。第一次还能扛得住,但第二次点击时就会OOMbreak;case 2:addBitmapToCache(BIG_IMAGE_PATH);//只要第一次不OOM,以后点击(相当于替换掉旧的Bitmap)也都不会OOMreturn;//直接返回case 3:bigBitmap = getBitmapFromCache(BIG_IMAGE_PATH);//直接从缓存中取得,可以看到点击后响应非常快break;case 4:weakBitmap = BitmapFactory.decodeFile(BIG_IMAGE_PATH);weakReference = new WeakReference<Bitmap>(weakBitmap);//此后将weakBitmap置为null也不影响weakReference中的Bitmapreturn;//直接返回case 5:bigBitmap = weakReference.get();//同样响应非常快break;}if (bigBitmap != null) {imageView.setImageBitmap(bigBitmap);tv_info.setText(formatInfo(bigBitmap));} else Toast.makeText(this, "文件或缓存不存在", Toast.LENGTH_SHORT).show();}}private String formatInfo(Bitmap bitmap) {StringBuffer buffer = new StringBuffer();buffer.append("内存中bitmap的大小为:" + bitmap.getByteCount() + " = " + bitmap.getByteCount() / 1024 / 1024 + "M");buffer.append("\n宽" + bitmap.getWidth() + " * 高" + bitmap.getHeight() + " * 参数" + 4 + " = " + bitmap.getWidth() * bitmap.getHeight() * 4);return buffer.toString();}/**按照指定的大小加载图片到内存,实际大小基本上不可能是指定的这个大小,因为图片会按照自己的规则进行缩放*/public Bitmap decodeSampledBitmapFromFile(String pathName, int reqWidth, int reqHeight) {BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeFile(pathName, options);options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);options.inJustDecodeBounds = false;return BitmapFactory.decodeFile(pathName, options);}/**在保证解析出的bitmap宽高分别大于目标尺寸宽高的前提下,取可能的inSampleSize的最大值*/public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {int width = options.outWidth;int height = options.outHeight;tv_info.setText("原始图片的宽高:" + width + "-" + height);//3600-5400int inSampleSize = 1;if (height > reqHeight || width > reqWidth) {int halfHeight = height / 2;int halfWidth = width / 2;while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {inSampleSize *= 2;}}return inSampleSize;}/**添加软引用Bitmap到Map中,使其缓存*/public void addBitmapToCache(String path) {imageCaches.put(path, new SoftReference<Bitmap>(BitmapFactory.decodeFile(path)));}/** 从缓存中取软引用的Bitmap对象*/public Bitmap getBitmapFromCache(String path) {SoftReference<Bitmap> softBitmap = imageCaches.get(path);if (softBitmap != null) {//如果软引用还存在,那么直接就可以获取这个对象的相关数据...这样就实现了cache...return softBitmap.get();} else {//如果已经不存在,表示GC已经将其回收,我们需要重新实例化对象,获取数据信息(一般直接返回null)//addBitmapToCache(path);//return getBitmapFromCache(path);return null;}}public void clearCache() {imageCaches.clear();}}
【软引用】弱引用 图片的加载与缓存 OOM的更多相关文章
- Android新浪微博客户端(七)——ListView中的图片异步加载、缓存
原文出自:方杰|http://fangjie.info/?p=193转载请注明出处 最终效果演示:http://fangjie.sinaapp.com/?page_id=54 该项目代码已经放到git ...
- Android-Universal-Image-Loader 图片异步加载类库的使用
在博客中看到一篇利用组件进行图片异步加载的文章在此作记录 原文:http://blog.csdn.net/vipzjyno1/article/details/23206387 这个图片异步加载并缓存的 ...
- Android图片异步加载框架Android-Universal-Image-Loader
版权声明:本文为博主原创文章,未经博主允许不得转载. Android-Universal-Image-Loader是一个图片异步加载,缓存和显示的框架.这个框架已经被很多开发者所使用,是最常用的几个 ...
- Android-Universal-Image-Loader 图片异步加载类库的使用(超详细配置)
这个图片异步加载并缓存的类已经被很多开发者所使用,是最常用的几个开源库之一,主流的应用,随便反编译几个火的项目,都可以见到它的身影. 可是有的人并不知道如何去使用这库如何进行配置,网上查到的信息对于刚 ...
- 【转】Android-Universal-Image-Loader 图片异步加载类库的使用(超详细配置)
Android-Universal-Image-Loader 原文地址:http://blog.csdn.net/vipzjyno1/article/details/23206387 这个图片异步加载 ...
- Universal-Image-Loader 图片异步加载类库的使用
这个图片异步加载并缓存的类已经被很多开发者所使用,是最常用的几个开源库之一,主流的应用,随便反编译几个火的项目,都可以见到它的身影. 可是有的人并不知道如何去使用这库如何进行配置,网上查到的信息对于刚 ...
- Android图片异步加载
原:http://www.cnblogs.com/angeldevil/archive/2012/09/16/2687174.html 相关:https://github.com/nostra13/A ...
- [学习总结]9、Android-Universal-Image-Loader 图片异步加载类库的使用(超详细配置)
这个图片异步加载并缓存的类已经被很多开发者所使用,是最常用的几个开源库之一,主流的应用,随便反编译几个火的项目,都可以见到它的身影. 可是有的人并不知道如何去使用这库如何进行配置,网上查到的信息对于刚 ...
- TypeError: 无法设置未定义或 null 引用的属性“src” ——IE浏览器不兼容图片懒加载vueLazy
异常分析: 谷歌浏览器访问正常,IE浏览器访问部分图片无法正常展示,查看控制台,输入如下错误信息: 经分析,只有使用过图片懒加载的地方图片展示才有问题,那么就应该是图片懒加载vue-lazyload这 ...
随机推荐
- 基于spring-boot的应用程序的单元+集成测试方案
目录 概述 概念解析 单元测试和集成测试 Mock和Stub 技术实现 单元测试 测试常规的bean 测试Controller 测试持久层 集成测试 从Controller开始测试 从中间层开始测试 ...
- CAT 3.0 开源发布,支持多语言客户端及多项性能提升
项目背景 CAT(Central Application Tracking),是美团点评基于 Java 开发的一套开源的分布式实时监控系统.美团点评基础架构部希望在基础存储.高性能通信.大规模在线访问 ...
- MCI:移动持续集成在大众点评的实践
一.背景 美团是全球最大的互联网+生活服务平台,为3.2亿活跃用户和500多万的优质商户提供一个连接线上与线下的电子商务服务.秉承“帮大家吃得更好,生活更好”的使命,我们的业务覆盖了超过200个品类和 ...
- nyoj zb的生日
zb的生日 时间限制:3000 ms | 内存限制:65535 KB 难度:2 描述 今天是阴历七月初五,acm队员zb的生日.zb正在和C小加.never在武汉集训.他想给这两位兄弟买点什么庆祝 ...
- 线性表之顺序表C++实现
线性表之顺序表 一.头文件:SeqList.h //顺序线性表的头文件 #include<iostream> ; //定义顺序表SeqList的模板类 template<class ...
- zookeeper【5】分布式锁
我们常说的锁是单进程多线程锁,在多线程并发编程中,用于线程之间的数据同步,保护共享资源的访问.而分布式锁,指在分布式环境下,保护跨进程.跨主机.跨网络的共享资源,实现互斥访问,保证一致性. 架构图: ...
- bzoj 3669 lct维护最小生成树
大概题意:给一个无向图,有a,b两种边权,找一条从1到n的路径,使得max(a[i])+max(b[i])最小a[i],b[i]表示该路径上的边的对应权. 如果用类似最短路的DP来做,显然每个点的状态 ...
- spring---aop(3)---Spring AOP的拦截器链
写在前面 时间断断续续,这次写一点关于spring aop拦截器链的记载.至于如何获取spring的拦截器,前一篇博客已经写的很清楚(spring---aop(2)---Spring AOP的JDK动 ...
- 最小生成树-普利姆算法eager实现
算法描述 在普利姆算法的lazy实现中,参考:普利姆算法的lazy实现 我们现在来考虑这样一个问题: 我们将所有的边都加入了优先队列,但事实上,我们真的需要所有的边吗? 我们再回到普利姆算法的lazy ...
- sql 递归查询所有的下级
--> 生成测试数据表: [tb] IF OBJECT_ID('[Users]') IS NOT NULL DROP TABLE [Users] GO CREATE TABLE [Use ...