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         }
原文地址:https://www.cnblogs.com/all88/p/3345704.html