Android 软引用
在项目中经常用到加载大图片内存溢出的问题,软引用能够有效的解决该问题
1 public class BitmapCache { 2 static private BitmapCache cache; 3 /** 用于Chche内容的存储 */ 4 private Hashtable<Integer, MySoftRef> hashRefs; 5 /** 垃圾Reference的队列(所引用的对象已经被回收,则将该引用存入队列中) */ 6 private ReferenceQueue<Bitmap> q; 7 8 /** 9 * 继承SoftReference,使得每一个实例都具有可识别的标识。 10 */ 11 private class MySoftRef extends SoftReference<Bitmap> { 12 private Integer _key = 0; 13 14 public MySoftRef(Bitmap bmp, ReferenceQueue<Bitmap> q, int key) { 15 super (bmp, q); 16 _key = key; 17 } 18 } 19 20 private BitmapCache() { 21 hashRefs = new Hashtable<Integer, MySoftRef>(); 22 q = new ReferenceQueue<Bitmap>(); 23 } 24 25 /** 26 * 取得缓存器实例 27 */ 28 public static BitmapCache getInstance() { 29 if (cache == null ) { 30 cache = new BitmapCache(); 31 } 32 return cache; 33 } 34 35 /** 36 * 以软引用的方式对一个Bitmap对象的实例进行引用并保存该引用 37 */ 38 private void addCacheBitmap(Bitmap bmp, Integer key) { 39 cleanCache(); // 清除垃圾引用 40 MySoftRef ref = new MySoftRef(bmp, q, key); 41 hashRefs.put(key, ref); 42 } 43 44 /** 45 * 依据所指定的drawable下的图片资源ID号(可以根据自己的需要从网络或本地path下获取),重新获取相应Bitmap对象的实例 46 */ 47 public Bitmap getBitmap( int resId, Context context) { 48 Bitmap bmp = null ; 49 // 缓存中是否有该Bitmap实例的软引用,如果有,从软引用中取得。 50 if (hashRefs.containsKey(resId)) { 51 MySoftRef ref = (MySoftRef) hashRefs.get(resId); 52 bmp = (Bitmap) ref.get(); 53 } 54 // 如果没有软引用,或者从软引用中得到的实例是null,重新构建一个实例, 55 // 并保存对这个新建实例的软引用 56 if (bmp == null ) { 57 // 传说decodeStream直接调用JNI>>nativeDecodeAsset()来完成decode, 58 // 无需再使用java层的createBitmap,从而节省了java层的空间。 59 bmp = BitmapFactory.decodeStream(context.getResources() 60 .openRawResource(resId)); 61 this .addCacheBitmap(bmp, resId); 62 } 63 return bmp; 64 } 65 66 private void cleanCache() { 67 MySoftRef ref = null ; 68 while ((ref = (MySoftRef) q.poll()) != null ) { 69 hashRefs.remove(ref._key); 70 } 71 } 72 73 /** 74 * 清除Cache内的全部内容 75 */ 76 public void clearCache() { 77 cleanCache(); 78 hashRefs.clear(); 79 System.gc(); 80 System.runFinalization(); 81 } 82 }
另外在介绍两个方法,从sd卡目录获取图片生成bitmap和从资源目录获取图片生成bitmap
1、从sd卡目录获取图片,生成bitmap
第一种方式:
private Bitmap getBitmap(String address) { Bitmap btp = null; FileInputStream fis; try { fis = new FileInputStream(new File(address)); BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = false; options.inSampleSize = 2; // width,hight设为原来的二分一 btp = BitmapFactory.decodeStream(fis, null, options); } catch (FileNotFoundException e) { e.printStackTrace(); } return btp; }
这种方式可以动态的对图片进行压缩,避免内存溢出,另外一种方式则特别简单
1 public Bitmap loadImageFromLocal(String path) { 2 return BitmapFactory.decodeFile(path); 3 }
2、从资源目录获取图片生成bitmap
1 private Bitmap getBitmap(int id){ 2 InputStream is = this.getResources().openRawResource(id); 3 BitmapFactory.Options options = new BitmapFactory.Options(); 4 options.inJustDecodeBounds = false; 5 options.inSampleSize = 1; 6 7 Bitmap btp = BitmapFactory.decodeStream(is, null, options); 8 return btp; 9 }