一丶源码见本文
二丶演示(略)
三丶课程讲解
/** * 磁盘缓存 工具类 */ public class DiskLruCacheUtils { private static DiskLruCacheUtils diskLruCacheUtils; //磁盘缓存插件 private DiskLruCache diskLruCache; private Context context; private DiskLruCacheUtils() { } ; /** * 单例 提供实例 * * @return */ public static DiskLruCacheUtils getInstance() { if (diskLruCacheUtils == null) { diskLruCacheUtils = new DiskLruCacheUtils(); } return diskLruCacheUtils; } /** * 磁盘缓存 * * @param context * @param disk_cache_subdir :缓存目录 * @param disk_cache_size :缓存大小 */ public void open(Context context, String disk_cache_subdir, int disk_cache_size) { try { this.context = context; /*** * open()方法 接收四个参数, * 第一个参数指定的是数据的缓存地址 * 第二个参数拽定当前应用程序的版本号 * 第三个参数 指定一个key 可以对应多个缓存文件,基本都是传1 * 第四个参数指定最多可以缓存多少字节的数据,通常10MB */ diskLruCache = diskLruCache.open(getCacheDir(disk_cache_subdir), getAppVersion(), 1, disk_cache_size); } catch (Exception e) { e.printStackTrace(); } } /** * 根据key 获取 磁盘缓存 * * @param url * @return */ public InputStream get(String url) { String key = hashkeyForDisk(url); try { DiskLruCache.Snapshot snapshot = diskLruCache.get(key); if (snapshot != null) { return snapshot.getInputStream(0);//拿 第几个图片,因为存的时侯是 1 } } catch (IOException e) { e.printStackTrace(); } return null; } /** * 磁盘 缓存 存入方法 * * @param url */ public void put(final String url) { new AsyncTask<String, Void, Void>() { @Override protected Void doInBackground(String... params) { //计算 md5 的摘要转化为十六进制的字符串,做为存入的键 ,相同的字符串,计算出来是一样 String key = hashkeyForDisk(params[0]); DiskLruCache.Editor editor = null; try { URL uri = new URL(params[0]); HttpURLConnection conn = (HttpURLConnection) uri.openConnection(); //key作用:存入图片的key值 editor = diskLruCache.edit(key); //输入输出缓存流 BufferedOutputStream out = new BufferedOutputStream(editor.newOutputStream(0), 8 * 1024); BufferedInputStream in = new BufferedInputStream(conn.getInputStream(), 8 * 1024); byte[] bytes = new byte[1024]; int len = -1; //写入磁盘缓存 while ((len = in.read(bytes)) != -1) { out.write(bytes, 0, len); } out.close(); in.close(); editor.commit(); conn.disconnect(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { try { editor.abort();//放弃写入 } catch (IOException e1) { e1.printStackTrace(); } e.printStackTrace(); } return null; } }; } /** * 计算字符 MD5 摘要 * * @param key * @return */ private String hashkeyForDisk(String key) { String cacheKey; try { final MessageDigest messageDigest = MessageDigest.getInstance("MD5"); messageDigest.update(key.getBytes()); //将字符串摘要 计算为 十六进制的 字符串 作为 key cacheKey = bytestoHexString(messageDigest.digest()); } catch (NoSuchAlgorithmException e) { cacheKey = String.valueOf(key.hashCode()); e.printStackTrace(); } return cacheKey; } /** * 计算为 十六进制的 字符串 * * @param digest * @return */ private String bytestoHexString(byte[] digest) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < digest.length; i++) { String hex = Integer.toHexString(0xFF & digest[i]); if (hex.length() == 1) { sb.append('0'); } else { sb.append(hex); } } return sb.toString(); } /** * 获取缓存 目录 * * @param name :缓存文件 * @return sdcard 上的 私有目录 * context.getExternalCacheDir().getPath() :在 mnt/sdcard/android/data/应用程序包/cache文件夹路径 * <p/> * 安装应用程序下的 私有目录 * context.getCacheDir().getPath() :在 data/data/应用程序包/cache */ private File getCacheDir(String name) { String cachePath = Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED || !Environment.isExternalStorageRemovable() ? context.getExternalCacheDir().getPath() : context.getCacheDir().getPath(); return new File(cachePath + File.separator + name); } /** * 获取当前应用程序的版本 */ public int getAppVersion() { try { return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return 1; } }
//本地内存缓存实例 public class MainActivity extends AppCompatActivity { private ImageView imageView; private LruCache<String, Bitmap> lruCache; private DiskLruCacheUtils diskLruCacheUtils; //磁盘缓存文件名 private static final String DISK_CACHE_SUBDIR = "temp"; //磁盘缓存空间大小 private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView = (ImageView) findViewById(R.id.imageView); //获取当前activity的内存大小 ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); int memoryClass = am.getMemoryClass(); //计算缓存的大小 字节 8/1 的内存作为缓存大小 final int cacheSize = memoryClass / 8 * 1024 * 1024; lruCache = new LruCache<>(cacheSize); diskLruCacheUtils = DiskLruCacheUtils.getInstance(); diskLruCacheUtils.open(this, DISK_CACHE_SUBDIR, DISK_CACHE_SIZE); } /** * 显示图片 * * @param view */ public void show(View view) { String key = String.valueOf(R.mipmap.as); Bitmap bitmap = getBitmapCache(key); //不缓存中没有时,则再去找 if (bitmap == null) { //获取 采样 缩放的位图 bitmap = decodeSampleBitmapFromResource(getResources(), R.mipmap.as, 100, 100); //图片存入缓存中 addBitmapCache(key, bitmap); } else { System.out.print("lruCache:缓存了"); } imageView.setImageBitmap(bitmap); } //添加到缓存 public void addBitmapCache(String key, Bitmap bitmap) { if (getBitmapCache(key) == null) { lruCache.put(key, bitmap); } } //从缓存中 读取对象 public Bitmap getBitmapCache(String key) { return lruCache.get(key); } /** * 位图重样 采样 * * @param res :资源对象 * @param resid :资源的id * @param reqWidth :要显示的宽 * @param reqHeight:要显示的高 * @return */ public Bitmap decodeSampleBitmapFromResource(Resources res, int resid, int reqWidth, int reqHeight) { BitmapFactory.Options options = new BitmapFactory.Options(); //只解析边界,不占用内存 options.inJustDecodeBounds = true; //得到边界的 宽 和 高 ,并存入 options中 BitmapFactory.decodeResource(res, resid, options); //得到缩放 值 options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false;// false :图片加载到内存中去 //再解码,这时图片就加载到内存中了,这时的图片是 缩放比例后的图片 return BitmapFactory.decodeResource(res, resid, options); } /** * 计算位图的 采样比例 * * @param options * @param reqWidth :必须的宽 * @param reqHeight * @return */ public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { //获取位图的原大小 int w = options.outWidth; int h = options.outHeight; int inSampleSize = 1; if (w > reqWidth || h > reqHeight) { if (w > h) { inSampleSize = Math.round((float) h / (float) reqHeight); } else { inSampleSize = Math.round((float) w / (float) reqWidth); } } return inSampleSize; } }