美文网首页
安卓保存多张图片到本地

安卓保存多张图片到本地

作者: remax1 | 来源:发表于2020-07-14 15:55 被阅读0次

前言

本篇主要仿照Glide完成图片三级缓存(内存-磁盘-网络),此外,我还加了一个内存复用池,用来复用已经申请好内存空间的bitmap对象的复用,为啥要自己写个Glide呢?因为要定义自己的磁盘缓存规则,场景就是不同的用户保存到不同的磁盘文件中,来完成磁盘图片文件跟用户绑定上传的功能。

三级缓存

private ActiveCache activeCache; // 活动缓存
    private MemoryCache memoryCache; // 内存缓存
    private DiskLruCacheImpl diskLruCache; // 磁盘缓存
    private Set<WeakReference<Value>> reusablePool;//内存复用池

Glide在内存缓存中加了一层设计,就是分为活动缓存和内存缓存。内存缓存采用Lrucache来缓存尚未被GC回收的图片,活动缓存则是缓存正在使用的图片,内存缓存和活动缓存中的图片是互斥的,就是正在使用的图片不会在内存缓存中,在内存缓存中的图片不会在活动缓存,这就是Glide第一级缓存,内存缓存。
Glide缓存二之磁盘缓存,这里采用LruDiskCache,也是github开源的一个项目,这里重点介绍下,因为这里涉及到比较多的设计:
1.前面提到了内存复用池,自然从磁盘加载到内存中时,首先看看内存复用池是否有满足条件的内存区域可以使用:

 private boolean isBitmapReusable(Bitmap bitmap,int w,int h,int inSampleSize){
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT){
          //版本控制,这里必须要相等才能复用
            return bitmap.getWidth() == w && bitmap.getHeight() == h && inSampleSize==1;
        }

        if (inSampleSize > 1){
            w /= inSampleSize;
            h /= inSampleSize;
        }
        int byteCount = getBytesPerPixel(bitmap.getConfig());
        //复用的内存池必须大于或者等于从磁盘加载的图片文件的字节数
        return byteCount <= bitmap.getAllocationByteCount();
    }

缓存三之网络缓存,当内存和磁盘都未命中时,此时就要去加载外部资源,我这里只写了网络的情况,

if (responseCode == HttpURLConnection.HTTP_OK) {
                inputStream = httpURLConnection.getInputStream();
                byte[] inputStream2ByteArr = inputStream2ByteArr(inputStream);
                //TODO 网络上获取图片 模拟接收过程。

                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = true;
//如果直接decodeStream 的话,二次开启的时候返回的bitmap为空,这里转化为字节数组

                BitmapFactory.decodeByteArray(inputStream2ByteArr,0,inputStream2ByteArr.length,options);

                int w = options.outWidth;
                int h = options.outHeight;

                options.inSampleSize = caculateInsampleSize(w,h,80,80);

                options.inJustDecodeBounds = false;

                options.inMutable =true;//设置可变
                options.inBitmap = reusable;

                final Bitmap bitmap =  BitmapFactory.decodeByteArray(inputStream2ByteArr,0,inputStream2ByteArr.length,options);

options.inMutable =true,这个就是为了内存复用做准备,首先要设置图片可变才能复用,加载完成图片后,在调用diskLrucache.put(key,value)方法,这里可以把key缓存下来,这个key就是图片url经过加密后的字符串,在遍历key集合,就可以完成多图的保存了。

关于磁盘缓存地址选择

  public static File getDiskCacheDir(Context context, String uniqueName) {
        String cachePath;

        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
                || !Environment.isExternalStorageRemovable()) {

            cachePath = context.getExternalCacheDir().getPath();

        } else {
            cachePath = context.getCacheDir().getPath();
        }
        return new File(cachePath + File.separator + uniqueName);
    }

这里做了个判断,是否有SD卡,有SD卡,才能储存到应用私有目录中去。

总结

写的比较简单,有问题的话可以留言,我在详细一些去介绍,网上的三级缓存太多了,这里参照Gilde来写,用法和Glide一样。

源码地址:https://github.com/doubizhu/Gildelib

相关文章

网友评论

      本文标题:安卓保存多张图片到本地

      本文链接:https://www.haomeiwen.com/subject/ijhaqktx.html