Android本地缓存DiskLruCache完整详细学习示例
package cc.vv; import java.io.File; import java.io.InputStream; import java.io.OutputStream; import libcore.io.DiskLruCache; import libcore.io.Utils; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.widget.ImageView; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; /** * Demo描述: * DiskLruCache学习示例 * * DiskLruCache用于本地缓存. * 比如在网络可用时加载一张网络图片,当网络不可用时依然可以显示该图片。 * 实现的原理是将图片保存到本地;当网络不可用时从本地加载图片。 * 在此简单模拟该过程,步骤如下: * 1 从网络下载图片且保存至DiskLruCache * 2 从DiskLruCache中获取缓存图片进行显示 * * * 学习备注: * 1 DiskLruCache的本地缓存文件路径为: * /sdcard/Android/data/<application package>/cache * 当应用被卸载时该文件亦会被删除 * 2 新闻类APP一般的做法.从新闻列表(ListView)中点击某条新闻跳转到详细画面. * 在详细画面一般有图片和文字.此时可以将图片和文字用同一个key存到不同的缓存文件夹下. * 在断网时浏览该新闻时候依据该key分别取出对应的图片和文字即可. * 3 在示例中用到了DiskLruCache的存和取的相关API.在此对其余重要API简要整理: * 3.1 remove(String key) 删除某个已缓存的对象. * 3.2 size() 得到缓存路径下缓存的总大小.这个很常见.许多APP都提示当前有多少缓存. * 3.3 flush() 将内存中的操作记录同步到日志文件(也就是journal文件)中 * 一般在Activity的onPause()中调用该方法. * 3.4 close() 关闭DiskLruCache.该方法与open方法对应. * 一般在Activity的onDestory()中调用该方法. * 3.5 delete() 将缓存数据全部删除. * * * 学习资源: * http://blog.csdn.net/guolin_blog/article/details/28863651 * Thank you very much */ public class MainActivity extends Activity { private ImageView mImageView; private DiskLruCache mDiskLruCache; private Context mContext; //DiskLruCache中对于图片的最大缓存值. private int maxSize=20*1024*1024; private String mImagePath="http://www.baidu.com/img/bdlogo.png"; private Handler mHandler; private final int FINISH=9527; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); init(); } private void init(){ try { mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what==FINISH) { getDataFromDiskLruCache(); } } }; mContext=this; mImageView=(ImageView) findViewById(R.id.imageView); initDiskLruCache(); } catch (Exception e) { // TODO: handle exception } } /** * 初始化DiskLruCache */ private void initDiskLruCache(){ try { File cacheDir=Utils.getDiskLruCacheDir(mContext, "bitmap"); if (!cacheDir.exists()) { cacheDir.mkdirs(); } int versionCode=Utils.getAppVersionCode(mContext); mDiskLruCache=DiskLruCache.open(cacheDir, versionCode, 1, maxSize); saveDataToDiskLruCache(); } catch (Exception e) { // TODO: handle exception } } // 将数据写入DiskLruCache private void saveDataToDiskLruCache() { new Thread(new Runnable() { @Override public void run() { try { //第一步:获取将要缓存的图片的对应唯一key值. String key = Utils.getStringByMD5(mImagePath); //第二步:获取DiskLruCache的Editor DiskLruCache.Editor editor = mDiskLruCache.edit(key); if (editor!=null) { //第三步:从Editor中获取OutputStream OutputStream outputStream=editor.newOutputStream(0); //第四步:下载网络图片且保存至DiskLruCache图片缓存中 boolean isSuccessfull=Utils.getBitmapFromNetWorkAndSaveToDiskLruCache(mImagePath, outputStream); if (isSuccessfull) { editor.commit(); mHandler.sendEmptyMessage(FINISH); }else{ editor.abort(); } mDiskLruCache.flush(); } } catch (Exception e) { } } }).start(); } //从DiskLruCache中读取数据 private void getDataFromDiskLruCache(){ try { //第一步:获取已缓存的图片的对应唯一key值. String key = Utils.getStringByMD5(mImagePath); //第二步:依据key获取到其对应的snapshot DiskLruCache.Snapshot snapshot=mDiskLruCache.get(key); if (snapshot!=null) { //第三步:从snapshot中获取到InputStream InputStream inputStream=snapshot.getInputStream(0); Bitmap bitmap=BitmapFactory.decodeStream(inputStream); mImageView.setImageBitmap(bitmap); } } catch (Exception e) { } } }
Utils如下:
package libcore.io; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import org.apache.http.HttpStatus; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Environment; public class Utils { /** * 获取DiskLruCache的缓存文件夹 * 注意第二个参数dataType * DiskLruCache用一个String类型的唯一值对不同类型的数据进行区分. * 比如bitmap,object等文件夹.其中在bitmap文件夹中缓存了图片. * * 缓存数据的存放位置为: * /sdcard/Android/data/<application package>/cache * 如果SD卡不存在时缓存存放位置为: * /data/data/<application package>/cache * */ public static File getDiskLruCacheDir(Context context, String dataType) { String dirPath; File cacheFile = null; if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || !Environment.isExternalStorageRemovable()) { dirPath=context.getExternalCacheDir().getPath(); } else { dirPath=context.getCacheDir().getPath(); } cacheFile=new File(dirPath+File.separator+dataType); return cacheFile; } /** * 获取APP当前版本号 * @param context * @return */ public static int getAppVersionCode(Context context){ int versionCode=1; try { String packageName=context.getPackageName(); PackageManager packageManager=context.getPackageManager(); PackageInfo packageInfo=packageManager.getPackageInfo(packageName, 0); versionCode=packageInfo.versionCode; } catch (NameNotFoundException e) { e.printStackTrace(); } return versionCode; } /** * 将字符串用MD5编码. * 比如在改示例中将url进行MD5编码 */ public static String getStringByMD5(String string) { String md5String = null; try { // Create MD5 Hash MessageDigest messageDigest = MessageDigest.getInstance("MD5"); messageDigest.update(string.getBytes()); byte messageDigestByteArray[] = messageDigest.digest(); if (messageDigestByteArray == null || messageDigestByteArray.length == 0) { return md5String; } // Create hexadecimal String StringBuffer hexadecimalStringBuffer = new StringBuffer(); int length = messageDigestByteArray.length; for (int i = 0; i < length; i++) { hexadecimalStringBuffer.append(Integer.toHexString(0xFF & messageDigestByteArray[i])); } md5String = hexadecimalStringBuffer.toString(); return md5String; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return md5String; } /** * 从网络获取图片且保存至SD卡中的缓存 */ public static boolean getBitmapFromNetWorkAndSaveToDiskLruCache(String imageUrl,OutputStream outputStream){ boolean isSuccessfull=false; URL url=null; HttpURLConnection httpURLConnection=null; BufferedOutputStream bufferedOutputStream=null; InputStream inputStream=null; BufferedInputStream bufferedInputStream=null; try { url=new URL(imageUrl); httpURLConnection=(HttpURLConnection) url.openConnection(); httpURLConnection.setConnectTimeout(5*1000); httpURLConnection.setReadTimeout(10*1000); httpURLConnection.setDoInput(true); httpURLConnection.setDoOutput(true); if (httpURLConnection.getResponseCode()==HttpStatus.SC_OK) { bufferedOutputStream=new BufferedOutputStream(outputStream); inputStream=httpURLConnection.getInputStream(); bufferedInputStream=new BufferedInputStream(inputStream); int len=0; byte [] buffer=new byte[1024]; while((len=bufferedInputStream.read(buffer))!=-1){ bufferedOutputStream.write(buffer, 0, len); bufferedOutputStream.flush(); } isSuccessfull=true; } else { isSuccessfull=false; System.out.println("图片请求失败"); } } catch (Exception e) { isSuccessfull=false; System.out.println("e="+e.toString()); }finally{ try { if (bufferedOutputStream!=null) { bufferedOutputStream.close(); } if (inputStream!=null) { inputStream.close(); } if (bufferedInputStream!=null) { bufferedInputStream.close(); } if (httpURLConnection!=null) { httpURLConnection.disconnect(); } } catch (Exception e) { System.out.println("e="+e.toString()); } } return isSuccessfull; } }
main.xml如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" /> </RelativeLayout>
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。