DiskLruCache本地缓存图片技术精炼详解

一、前期基础知识储备

上一篇文章《LruCache内存缓存图片技术精炼详解》中,笔者分析了利用LruCache类实现图片的内存缓存,在应用程序中,如果已经联网加载好了图片,那么把图片保存到内存中,下一次加载就会十分迅速。但是,内存缓存技术,也有缺点,如果图片从内存里被移除了的话,那么下一次加载仍然是要从网络中获取,那么有没有什么办法可以做到一个“中间状态”,既不用每次从网络加载,又不用担心内存不足的问题。于是,Google又提供了一套硬盘缓存的解决方案:DiskLruCache,利用这类来实现本地的缓存,所以在下载完图片之后,既可以先保存在内存中,又可以保存在本地SD卡中,那么下一次加载这张图片就会十分迅速。

(1)DiskLruCache应用程序实践

每次我们打开一个图文app时,比如浏览器,都需要从网络中加载大量的图片,然后我们关闭这个应用程序,断开网络连接,下次再打开这个应用程序时,我们会发现上次加载的内容依旧保留着,这种应用程序都是运用了本地缓存的技术,非常常见。

(2)DiskLruCache本地缓存默认路径

通常情况下多数应用程序都会将缓存的位置选择为/sdcard/Android/data/<application package>/cache 这个路径,但DiskLruCache本身并没有限制存储的位置,我们也可以自己设置。

二、上代码,具体实现

由于DiskLruCache并不是由Google官方编写的,所以这个类并没有被包含在Android API当中,我们需要将这个类从网上下载下来,然后手动添加到项目当中。DiskLruCache的源码在Google Source上:GoogleSource

先实现本地存储文件过程

(1)新建DiskLruCache对象

//DiskLruCache实例,它的构造方法是私有的,所以我们需要通过它提供的open方法来生成。   
try {  
    mDiskLruCache = DiskLruCache.open(getDiskCacheDir(MyApplication.getContext(),CACHE_FOLDER_NAME),  
            getAppVersion(MyApplication.getContext()) , 1, DISKMAXSIZE);  
} catch (IOException e) {  
    e.printStackTrace();  
}

open()方法接收四个参数,第一个参数指定的是数据的缓存地址,第二个参数指定当前应用程序的版本号,第三个参数指定同一个key可以对应多少个缓存文件,一般都是传1,第四个参数指定最多可以缓存多少字节的数据。

获取应用程序的版本号,代码如下:

public int getAppVersion(Context context) {  
    try {  
        PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);  
        return info.versionCode;  
    } catch (NameNotFoundException e) {  
        e.printStackTrace();  
    }  
    return 1;  
} 

(2)开启新线程

文件的读写都是耗时操作,这里我们要开启支线程进行文件的读取操作

(3)创建DiskLruCache.Editor对象

    
try{
	String imageUrl = "http://xxx";  
    String key = hashKeyForDisk(imageUrl);  
    DiskLruCache.Editor editor = mDiskLruCache.edit(key);  
    if (editor != null) {  
        OutputStream outputStream = editor.newOutputStream(0);  
        if (downloadUrlToStream(imageUrl, outputStream)) {  
            editor.commit();  
        }
		} catch (IOException e) {  
		e.printStackTrace();  
	}

创建DiskLruCache.Editor对象,调用它的newOutputStream()方法来创建一个输出流,然后把它传入到downloadUrlToStream()中就能实现下载并写入缓存的功能。

注:newOutputStream()方法接收一个index参数,由于前面在设置valueCount的时候指定的是1,所以这里index传0就可以了。在写入操作执行完之后,我们还需要调用一下commit()方法进行提交才能使写入生效。

完整的本地存储代码如下:

new Thread(new Runnable() {  
    @Override  
    public void run() {  
        try {  
            String imageUrl = "http://xxx";  
            String key = hashKeyForDisk(imageUrl);  
            DiskLruCache.Editor editor = mDiskLruCache.edit(key);  
            if (editor != null) {  
                OutputStream outputStream = editor.newOutputStream(0);  
                if (downloadUrlToStream(imageUrl, outputStream)) {  
                    editor.commit();  
                } else {  
                    editor.abort();  
                }  
            }  
            mDiskLruCache.flush();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
}).start();

——————————————————我是分隔线——————————————————

接着来实现本地文件的读取过程

其实过程和本地存储过程很相似,就是读取的时候调用的是get()方法,存储的时候调用的是edit()方法。

try{
	String imageUrl = "http://xxx";  
	String key = hashKeyForDisk(imageUrl);  
	DiskLruCache.Snapshot snapShot = mDiskLruCache.get(key);  
	if (snapShot != null) {  
		nputStream inputStream = snapShot.getInputStream(0);  
		Bitmap bitmap = BitmapFactory.decodeStream(inputStream);  
		mImage.setImageBitmap(bitmap);  
			}  
		} catch (IOException e) {  
		e.printStackTrace();  
	}

总结:DiskLruCache是现在非常流行的用于实现本地图片缓存的技术,联网,是现在手机最大的特点之一,而联网之后,又会产生许多的数据,这些数据,如果每次打开都从网络重新获取一遍,对于用户本身是一种负担,因为读取网络内容的速度没有那么迅速,另外就是产生的流量消耗,也不可小觑。所以同时使用DiskLruCache本地缓存技术+LruCache内存缓存技术是现在应用程序非常常见的缓存技术。如果在加上一些非常流行的网络框架,比如Volley、OkHttp,那么请求网络数据,加载网络数据就会变得十分便捷,这就是现在很多的一个概念——“三级缓存”



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值