图片的三级缓存

public class ImageLoader {
    
    //一级缓存的最大数量
    private static final int MAX_CAPACTITY = 20;
    //下载图片时的默认图片
    private DefaultImage image = new DefaultImage();
    private Context mContext;
    
    private  ImageLoader(Context context){
        this.mContext = context;
    }
    private ImageLoader(){};
    
    private static ImageLoader instance;
    public static ImageLoader getInstance(Context context){
        if(instance == null){
            instance = new ImageLoader(context);
        }
        return instance;
        
    }
    
    
    //三级缓存
    //一级缓存 强引用 在内存溢出时 也不回收
    //20张
    
    /**
     * String bitmap的路径
     * bitmap 图片
     */
    private LinkedHashMap<String, Bitmap> firstCacheIma = new LinkedHashMap<String, Bitmap>(MAX_CAPACTITY, 0.75f, true){
        //根据返回值移除map中最老的值
        protected boolean removeEldestEntry(java.util.Map.Entry<String,Bitmap> eldest) {
            if(this.size() > MAX_CAPACTITY){
                
                //加入二级缓存  软引用 在内存不足,回收
                secondCache.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue()));
                
                //加入三级缓存 本地缓存
                diskCache(eldest.getKey(),eldest.getValue());                
            }
            return false;
        }
    };
    /**
     * 本地缓存
     * @param key 图片的路径 (会被当做名称保存到硬盘)
     * @param value
     */
    private void diskCache(String key, Bitmap value) {
        
        String name = MD5utils.decode(key);
        String path = mContext.getCacheDir().getAbsolutePath()+
                File.separator +name;
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(path);
            //保存成JPG格式
            value.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }finally{
            if(fos != null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        
    };
    
    //二级缓存,超过20张
    //线程安全 并发的
    private static ConcurrentHashMap<String, SoftReference<Bitmap>>  secondCache = 
            new ConcurrentHashMap<String, SoftReference<Bitmap>>();    
    
    //三级缓存;本地缓存 写入内部存储
    public void loadImage(String key,ImageView imageView){
        //读取缓存
        Bitmap bitmap = getFromCachr(key);
        if(bitmap != null){
            cancelDownload(key, imageView);
            imageView.setImageBitmap(bitmap);
        }else{
            //设置默认图片
            imageView.setImageDrawable(image);
            //访问网络
            AsynImagLoaderTask task = new AsynImagLoaderTask(imageView);
            task.execute(key);
        }        
    }    
    //异步下载图片
    class AsynImagLoaderTask extends AsyncTask<String, Void , Bitmap>{

        private String key;
        private ImageView imageView;
        
        
        public AsynImagLoaderTask(ImageView imageView) {
            super();
            this.imageView = imageView;
        }


        @Override
        protected Bitmap doInBackground(String... params) {
            key = params[0];
            return downLoadImag(key);
        }


        @Override
        protected void onPostExecute(Bitmap result) {
            super.onPostExecute(result);
            if(isCancelled()){
                result =null;
            }
            if(result != null){
            //添加到一级缓存
            addFirstCache( key, result);
            //显示图片
            imageView.setImageBitmap(result);
            }
      
        }        
    }
    
    private void cancelDownload(String key,ImageView result){
        //可能有多个任务下载同一张图片
        AsynImagLoaderTask task = new AsynImagLoaderTask(result);
        if( task != null){
            String downKey = task.key;
            if(downKey == null || !downKey.equals(key)){
                //设置标识
                task.cancel(true);
            }
        }
    }

    /**
     * 加入一级缓存 
     * @param key2
     * @param result
     */
    private void addFirstCache(String key2, Bitmap result) {
        if(result != null){
            synchronized (firstCacheIma) {
                firstCacheIma.put(key2, result); 
                
            }
        }
    }

    private Bitmap getFromCachr(String key) {
        //从一级缓存加载
        synchronized (firstCacheIma) {
            Bitmap bitmap = firstCacheIma.get(key);
            //保持图片的新鲜
            if(bitmap != null){
                firstCacheIma.remove(bitmap);
                firstCacheIma.put(key, bitmap);
                return bitmap;                
            }
        }
        
        //从二级缓存加载
        SoftReference<Bitmap> softReference = secondCache.get(key);    
        if(softReference != null){
            Bitmap bitmap = softReference.get();
            if(bitmap != null){
                //添加到一级缓存
                firstCacheIma.put(key, bitmap);
                return bitmap;
            }
        }else{
            //软引用呗回收了,从缓存中清楚
            secondCache.remove(key);
        }
        //从本地缓存加载
        Bitmap load_bitmap = getFromLocal( key);
        if(load_bitmap != null){
            //添加到一级缓存
            firstCacheIma.put(key, load_bitmap);
            return load_bitmap;
        }
        return null;
    }
    
    /**
     * 从本地缓存中读取
     * @param key
     * @return
     */
    private Bitmap getFromLocal(String key) {
        String name = MD5utils.decode(key);
        if(name == null){
            return null;
        }
        String path = mContext.getCacheDir().getAbsolutePath() +
                File.separator + name;
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(path);
            return BitmapFactory.decodeStream(fis);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        
        return null;
    }

    /**
     * 下载图片
     * @param key2
     * @return
     */
    private Bitmap downLoadImag(String key2) {
        InputStream is = null;
        try {
            is = DownImag.getImag(key2);
            return BitmapFactory.decodeStream(is);
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(is != null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
     
    /**
     * 设置默认图片
     * 
     */
    static class DefaultImage extends ColorDrawable{
        public DefaultImage(){
            super(Color.GRAY);
        }
    }

}

Adapter中使用:

public class MyAdapter extends BaseAdapter{

    private Context context;
    private LayoutInflater inflater;
    private ImageLoader loader;
    private String[] str;
    public MyAdapter (Context context,String[] str){
        this.context = context;
        inflater = LayoutInflater.from(context);
        this.str= str;
        loader = ImageLoader.getInstance(context);
    }
    @Override
    public int getCount() {
        
        return str.length;
    }
    

    @Override
    public Object getItem(int position) {
        
        return str[position];
    }

    @Override
    public long getItemId(int position) {
        
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if(convertView == null){
             holder = new ViewHolder();
            convertView = inflater.inflate(com.example.test.R.layout.list_item, null);
            holder.imageView = (ImageView) convertView.findViewById(com.example.test.R.id.item);
            convertView.setTag(holder);
        }else{
            holder = (ViewHolder) convertView.getTag();
        }
        loader.loadImage(str[position], holder.imageView);
        return convertView;
    }
    
    class ViewHolder{
        ImageView imageView;
    }

}

Md5Utils

public class MD5utils {
    
    public static String decode(String key){
        MessageDigest digest = null;
        try {
            digest = MessageDigest.getInstance("MD5");
            digest.reset();
            //UTF-8编码
            
                digest.update(key.getBytes("utf-8"));
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            
        } catch (NoSuchAlgorithmException e) {
            
            e.printStackTrace();
        }        
        byte[] byteArray = digest.digest();
        StringBuffer buffer = new StringBuffer();
        for(int i = 0; i< byteArray.length;i++){
            
        }        
        return key;
        
    }

}

DownImage:

public class DownImag {
    
    public static InputStream getImag(String key) throws IOException{
        URL url = new URL(key);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        return connection.getInputStream();
    }
}
原文地址:https://www.cnblogs.com/wei1228565493/p/4676924.html