上个无奈的交接,基本没有写博客。在一次面试中被问到磁盘缓存答得有点尴尬。所以今天抽隔空回忆回忆。
参考:https://blog.csdn.net/guolin_blog/article/details/28863651
一,依赖(第一个是磁盘缓存的依赖,后面的是我demo需要的)compile 'com.jakewharton:disklrucache:2.0.2' compile files('libs/picasso-2.5.2.jar') compile files('libs/eventbus-3.0.0.jar')二,在activity的oncreate方法通过open创建磁盘的对象(下面代码是一个方法),open()方法接收四个参数,第一个参数指定的是数据的缓存地址,第二个参数指定当前应用程序的版本号,第三个参数指定同一个key可以对应多少个缓存文件,基本都是传1,第四个参数指定最多可以缓存多少字节的数据
public DiskLruCache getDiskLruCache() { try { File cacheDir = getDiskCacheDir(this, "bitmap"); if (!cacheDir.exists()) { cacheDir.mkdirs(); } mDiskLruCache = DiskLruCache.open(cacheDir, getAppVersion(this), 1, 10 * 1024 * 1024); } catch (IOException e) { e.printStackTrace(); } return mDiskLruCache; }
getDiskCacheDir是判断sd卡的状态,获取缓存文件。
public 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); }
getAppVersion方法获取应用版本号
public int getAppVersion(Context context) { try { PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); return info.versionCode; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return 1; }
三,第一次进入时网络展示图片,保存到缓存文件,后面的进入都是通过缓存提取。
private void judge() { new Thread(new Runnable() { @Override public void run() { //通过图片url通过md5生成唯一key值 String key = hashKeyForDisk(imageUrl); try { //通过磁盘缓存对象判断有没有缓存 DiskLruCache.Snapshot snapShot = mDiskLruCache.get(key); if (snapShot != null) { //有缓存 InputStream is = snapShot.getInputStream(0); Bitmap bitmap = BitmapFactory.decodeStream(is); imageview.setImageBitmap(bitmap); }else { //无缓存通过handle回到UI线程通过picasso展示图片 mHandler.sendEmptyMessage(1); //通过磁盘对象加入缓存 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(); }
hashKeyForDisk方法通过图片url通过md5生成唯一key值
public String hashKeyForDisk(String key) { String cacheKey; try { final MessageDigest mDigest = MessageDigest.getInstance("MD5"); mDigest.update(key.getBytes()); cacheKey = bytesToHexString(mDigest.digest()); } catch (NoSuchAlgorithmException e) { cacheKey = String.valueOf(key.hashCode()); } return cacheKey; }
downloadUrlToStream方法通过网络下载图片,保存到缓存文件
private boolean downloadUrlToStream(String urlString, OutputStream outputStream) { HttpURLConnection urlConnection = null; BufferedOutputStream out = null; BufferedInputStream in = null; try { final URL url = new URL(urlString); urlConnection = (HttpURLConnection) url.openConnection(); //in是网络过来的流 in = new BufferedInputStream(urlConnection.getInputStream(), 8 * 1024); //写入缓存的流 out = new BufferedOutputStream(outputStream, 8 * 1024); int b; while ((b = in.read()) != -1) { out.write(b); } return true; } catch (final IOException e) { e.printStackTrace(); } finally { if (urlConnection != null) { urlConnection.disconnect(); } try { if (out != null) { out.close(); } if (in != null) { in.close(); } } catch (final IOException e) { e.printStackTrace(); } } return false; }
布局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" 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="com.test.testlru.MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /> <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:id="@+id/imageview" android:src="@mipmap/ic_launcher" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>
完整activity
package com.test.testlru; import android.app.Activity; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.Button; import android.widget.ImageView; import com.jakewharton.disklrucache.DiskLruCache; import com.squareup.picasso.Picasso; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * Created by Administrator on 2018/5/18. */ public class AActivity extends Activity { DiskLruCache mDiskLruCache = null; private ImageView imageview; private Button btn; private String imageUrl = "http://img.zcool.cn/community/0171f25721807c6ac7253812b932f1.jpg@1280w_1l_2o_100sh.jpg"; protected Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { Picasso.with(AActivity.this).load(imageUrl).into(imageview); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageview = (ImageView) findViewById(R.id.imageview); btn = (Button) findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { try { //清除缓存 String key = hashKeyForDisk(imageUrl); mDiskLruCache.remove(key); } catch (IOException e) { e.printStackTrace(); } } }); //获取磁盘缓存的对象 mDiskLruCache = getDiskLruCache(); //网络加载缓存磁盘,无缓存时加入缓存 judge(); } /** * 第一次进入时网络展示图片,保存到缓存文件,后面的进入都是通过缓存提取。 */ private void judge() { new Thread(new Runnable() { @Override public void run() { //通过图片url通过md5生成唯一key值 String key = hashKeyForDisk(imageUrl); try { //通过磁盘缓存对象判断有没有缓存 DiskLruCache.Snapshot snapShot = mDiskLruCache.get(key); if (snapShot != null) { //有缓存 InputStream is = snapShot.getInputStream(0); Bitmap bitmap = BitmapFactory.decodeStream(is); imageview.setImageBitmap(bitmap); }else { //无缓存通过handle回到UI线程通过picasso展示图片 mHandler.sendEmptyMessage(1); //通过磁盘对象加入缓存 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(); } /** * 获取缓存对象 * @return */ public DiskLruCache getDiskLruCache() { try { File cacheDir = getDiskCacheDir(this, "bitmap"); if (!cacheDir.exists()) { cacheDir.mkdirs(); } mDiskLruCache = DiskLruCache.open(cacheDir, getAppVersion(this), 1, 10 * 1024 * 1024); } catch (IOException e) { e.printStackTrace(); } return mDiskLruCache; } /** * 通过网络下载图片,保存到缓存文件 * @param urlString * @param outputStream * @return */ private boolean downloadUrlToStream(String urlString, OutputStream outputStream) { HttpURLConnection urlConnection = null; BufferedOutputStream out = null; BufferedInputStream in = null; try { final URL url = new URL(urlString); urlConnection = (HttpURLConnection) url.openConnection(); //in是网络过来的流 in = new BufferedInputStream(urlConnection.getInputStream(), 8 * 1024); //写入缓存的流 out = new BufferedOutputStream(outputStream, 8 * 1024); int b; while ((b = in.read()) != -1) { out.write(b); } return true; } catch (final IOException e) { e.printStackTrace(); } finally { if (urlConnection != null) { urlConnection.disconnect(); } try { if (out != null) { out.close(); } if (in != null) { in.close(); } } catch (final IOException e) { e.printStackTrace(); } } return false; } /** * 通过图片url通过md5生成唯一key值 * @param key * @return */ public String hashKeyForDisk(String key) { String cacheKey; try { final MessageDigest mDigest = MessageDigest.getInstance("MD5"); mDigest.update(key.getBytes()); cacheKey = bytesToHexString(mDigest.digest()); } catch (NoSuchAlgorithmException e) { cacheKey = String.valueOf(key.hashCode()); } return cacheKey; } private String bytesToHexString(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < bytes.length; i++) { String hex = Integer.toHexString(0xFF & bytes[i]); if (hex.length() == 1) { sb.append('0'); } sb.append(hex); } return sb.toString(); } /** * 判断sd卡的状态,获取缓存文件 * @param context * @param uniqueName * @return */ public 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); } /** * 获取应用版本号 * @param context * @return */ public int getAppVersion(Context context) { try { PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); return info.versionCode; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return 1; } }