图片的三级缓存(手动)实现步骤

连网图片的处理:

  1. 在onBindViewHolder方法中获取本行对应的图片网址,根据图片网址下载图片

 

 

关于下载图片的缓存处理

方式一: 纯手动处理

  • 缓存处理的大体思路:

将下载好的图片分别存储在两个位置:

    1. 运行内存中

特点:页面退出时,清空

2. 本地

特点:只要不手动删除或者程序卸载,一致存在

 

 

每当要显示图片的时候,先去内存中读取图片,如果有图片,直接显示,如果没有图片,再到本地进行读取,如果没有下载。并且在下载后将图片分别存入内存和本地

 

 

图片的3级缓存

1.LruCache

  • 特点:
    •    默认支持存储键值对
    •    在初始化LruCache对象指定做多存储多少图片
    •    一旦达到最大存储上限时,会自动删除最先存储的图片,再将新图片添加到LruCache中

 

2.SoftReferences   软引用

  • 本身不支持存储n组键值对,每一个SoftReferences对象只能存储一张图片
  • 如果要通过存储多张图片,需要借助HashMap<String,SoftRerences>
  • 自动根据当前的内存情况存储图片,如果内存充足,那么一直存储图片
  • 如果内存不够用,会自动将存储的图片删除掉

3.本地

 

 

3级缓存的实现步骤:

图片的读取:

先读LruCache,没有读SoftReferences,再没有,读本地,再没有,连网

 

图片的存储

 

连网下载后将图片存入LruCache和本地

当LruCache中的图片被自动删除的时候,将删除的图片添加到SoftReferences中进行存储

 

 

class MyFirstAdapter extends RecyclerView.Adapter<MyFirstAdapter.MyViewHolder> {

    //LruCache对象
    
LruCache<String, Bitmap> cache;

    //创建HashMap对象,用于存储多张存入软引用的图片
    
HashMap<String, SoftReference<Bitmap>> map new HashMap<>();


    //在构造方法中初始化LruCache对象
    
public MyFirstAdapter() {
        //获取当前可用的运行内存的1/8
        
int maxSize = (int) (Runtime.getRuntime().maxMemory() / 8);
        //通过构造方法的参数指定当前LruCache中最多存储多少图片
        
cache new LruCache<String, Bitmap>(maxSize) {
            /*
            * 通过返回值获取当前要加到LruCache中的图片的大小
            * */
            
@Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getByteCount();
            }

            /*
            *  LruCache中的图片被删除时运行此方法
            *  evicted: 图片是否是被系统自动删除的
            * */
            
@Override
            protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {
                super.entryRemoved(evicted, key, oldValue, newValue);
                if (evicted) {
                    //图片被系统自动删除,可以在此处将删除的图片添加到SoftReferences中存储
                    
map.put(key,new SoftReference<Bitmap>(oldValue));
                }
            }
        };

    }


    //自定义方法,用于从缓存中取出图片
    
public Bitmap getCacheBitmap(String url) {
        //1. LruCache中取图片
        
Bitmap result = cache.get(url);
        if (result == null) {
            //2. SoftReferences中读取图片
            
SoftReference<Bitmap> soft = map.get(url);

            if (soft != null) {
                result = soft.get();  //从软引用中取出图片
                
if (result == null) {
                    //3. 从本地读取图片

                    
return result = BitmapFactory.decodeFile("data/data/" + getPackageName() + "/cache/" + url);

                }
            }
        }

        return result;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Log.i("====""======   onCreateViewholder");
        return new MyViewHolder(LayoutInflater.from(MainActivity.this)
                .inflate(R.layout.item, parent, false));
    }


    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {
        Log.i("====""======   onBindViewHolder  " + position);
        holder.tv.setText(list.get(position).getPicCategoryName());
        //设置imageview上显示的默认图片
        
holder.iv.setImageResource(R.mipmap.ic_launcher);
        //获取当前要显示的图片对应的图片网址
        
String url = list.get(position).getCategoryPic();
        //从缓存中取出图片
        
Bitmap bitmap = getCacheBitmap(url);

        if (bitmap != null) {
            //缓存中有图片
            
holder.iv.setImageBitmap(bitmap);
        } else {

            //缓存中没有图片,连网进行下载
            
new MyImgTask(new MyImgTask.DoImgBackListener() {
                @Override
                public void onBack(Bitmap t,String url) {
                        holder.iv.setImageBitmap(t);

                        // 将图片存入LruCache
                        
cache.put(url,t);

                        //将图片存入本地
                        //getPackageName()用于获取当前程序的程序包名
                        
File file = new File("data/data/" + getPackageName() + "/cache");
                        if (!file.exists()) {
                            file.mkdirs(); //如果文件夹不存在,创建文件夹
                        
}
                        try {
                            FileOutputStream fos = new FileOutputStream("data/data/" + getPackageName() + "/cache/"+url);
                            //将图片数据存入指定路径中
                            
t.compress(Bitmap.CompressFormat.PNG,100,fos);
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        }

                    }
            }).execute(url);
        }


    }

    //通过返回值控制列表中总共要显示多少个条目
    
@Override
    public int getItemCount() {
        return list.size();
    }

    /*
            * 创建一个ViewHolder的子类
            * 用于初始化item中控件对象
            * */
    
class MyViewHolder extends RecyclerView.ViewHolder {

        public TextView tv;
        public ImageView iv;

        //参数:列表中显示的item中的View对象
        
public MyViewHolder(View itemView) {
            super(itemView);
            tv = (TextView) itemView.findViewById(R.id.textView);
            iv = (ImageView) itemView.findViewById(R.id.imageView);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值