Android图片二级缓存

点击下载源代码

想起刚開始写代码的时候,领导叫我写一个头像下载的方法,当时屁颠屁颠就写了一个图片下载的,每次都要去网络上请求,最后直接被pass掉了

当时的思路是这种

后来渐渐地就知道了有二级缓存这东西。

自己也阅读过非常多关于双缓存的文章。

APP开发到越后面。对性能的要求越高。那么双缓存的优势就逐渐体现出来了。

所谓图片双缓存。首先到执行内存中请求,再到sd卡请求,最后到网络请求,流程图例如以下

那我们从第一部開始解析

1.先看 内存缓存的代码

[java] view
plain
copy

  1. public class MemoryCache implements ImageCache {
  2. private static final String TAG = MemoryCache.class.getSimpleName();
  3. private LruCache<String,Bitmap> mMemoryCache;
  4. public MemoryCache(){
  5. init();
  6. }
  7. private void init(){
  8. final int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024);
  9. final int cacheSize = maxMemory/4;
  10. mMemoryCache = new LruCache<String,Bitmap>(cacheSize){
  11. @Override
  12. protected int sizeOf(String key, Bitmap value) {
  13. return value.getRowBytes()*value.getHeight()/1024;
  14. }
  15. };
  16. }
  17. @Override
  18. public Bitmap get(String key) {
  19. Bitmap bitmap = mMemoryCache.get(key);
  20. if (bitmap!=null){
  21. Log.i(TAG,"File is exist in memory");
  22. }
  23. return mMemoryCache.get(key);
  24. }
  25. @Override
  26. public void put(String key, Bitmap bitmap) {
  27. if (get(key)==null) {
  28. mMemoryCache.put(key, bitmap);
  29. }
  30. }
  31. }

[java] view
plain
copy

  1. private void init()

init()方法中对一些变量进行初始化,mMemoryCache用于在内存中缓存图片

[java] view
plain
copy

  1. public Bitmap get(String key) {}

get()方法用于从内存中获得缓存

[java] view
plain
copy

  1. public void put(String key, Bitmap bitmap) {}

put()方法将下载好的图片缓存到内存中,方便下次使用

2.再看sd卡缓存

[java] view
plain
copy

  1. public class DiskCache implements ImageCache {
  2. private static final String TAG = DiskCache.class.getSimpleName();
  3. static String mPath ;
  4. public DiskCache(Context context){
  5. init(context);
  6. }
  7. private void init(Context context){
  8. // 获取图片缓存路径
  9. mPath = getDiskCachePath(context,"bitmap");
  10. File cacheDir = new File(mPath);
  11. if (!cacheDir.exists()) {
  12. cacheDir.mkdirs();
  13. }
  14. }
  15. @Override
  16. public Bitmap get(String key) {
  17. File file = new File(mPath+key);
  18. if (file.exists()){
  19. return BitmapFactory.decodeFile(mPath+key);
  20. }
  21. return null;
  22. }
  23. @Override
  24. public void put(String key, Bitmap bitmap) {
  25. FileOutputStream fileOutputStream = null;
  26. try {
  27. File file = new File(mPath+key);
  28. if (file.exists()){
  29. Log.i(TAG,"File is exist on disk");
  30. }
  31. fileOutputStream = new FileOutputStream(mPath+key);
  32. bitmap.compress(Bitmap.CompressFormat.PNG,100,fileOutputStream);
  33. } catch (FileNotFoundException e) {
  34. e.printStackTrace();
  35. }finally {
  36. CloseUtils.closeQuietly(fileOutputStream);
  37. }
  38. }
  39. /**
  40. * 依据传入的dir获得路径
  41. * @param context
  42. * @param dir
  43. * @return
  44. */
  45. public String getDiskCachePath(Context context, String dir) {
  46. String cachePath;
  47. if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
  48. || !Environment.isExternalStorageRemovable()) {
  49. cachePath = context.getExternalCacheDir().getPath();
  50. } else {
  51. cachePath = context.getCacheDir().getPath();
  52. }
  53. return cachePath + File.separator + dir;
  54. }
  55. }

相同

[java] view
plain
copy

  1. private void init()

init()方法中对一些变量进行初始化,mMemoryCache用于在内存中缓存图片

[java] view
plain
copy

  1. public Bitmap get(String key) {}

get()方法用于从内存中获得缓存

[java] view
plain
copy

  1. public void put(String key, Bitmap bitmap) {}

put()方法将下载好的图片缓存到内存中,方便下次使用

接下来我们会在一个叫DoubleCache的类中对以上两种缓存方式进行管理

[java] view
plain
copy

  1. public class DoubleCache implements ImageCache {
  2. private static final String TAG = DoubleCache.class.getSimpleName();
  3. private MemoryCache mMemoryCache = null;
  4. private DiskCache mDiskCache = null;
  5. public DoubleCache(Context context){
  6. mMemoryCache = new MemoryCache();
  7. mDiskCache = new DiskCache(context);
  8. }
  9. @Override
  10. public Bitmap get(String url) {
  11. String key = url2Key(url);
  12. Bitmap bitmap = mMemoryCache.get(key);
  13. if(bitmap==null){
  14. bitmap = mDiskCache.get(key);
  15. }else {
  16. }
  17. return bitmap;
  18. }
  19. @Override
  20. public void put(String url, Bitmap bitmap) {
  21. String key = url2Key(url);
  22. mMemoryCache.put(key,bitmap);
  23. mDiskCache.put(key,bitmap);
  24. }
  25. //url转key
  26. private String url2Key(String url){
  27. String key = MD5.hashKeyForDisk(url)+".jpg";
  28. return key;
  29. }
  30. }

我们在获取缓存的时候先从内存中获取。当内存中击中直接返回,当内存中没有击中,则訪问sd卡。

3.看到这里,小伙伴们一定急了,这仅仅有从缓存中和sd卡中取图片,并没有从网络获取,别急。立即就来

[java] view
plain
copy

  1. public class ImageLoader {
  2. private static final String TAG = ImageLoader.class.getSimpleName();
  3. private static ImageLoader sInstance;
  4. private DoubleCache mDoubleCache = null;
  5. private ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
  6. private ImageLoader(Context context) {
  7. mDoubleCache = new DoubleCache(context);
  8. }
  9. public static ImageLoader getInstance(Context context) {
  10. if (sInstance == null) {
  11. synchronized (ImageLoader.class) {
  12. sInstance = new ImageLoader(context);
  13. }
  14. }
  15. return sInstance;
  16. }
  17. public void displayImage(String url, ImageView imageView) {
  18. Bitmap bitmap = mDoubleCache.get(url);
  19. if (bitmap != null) {
  20. imageView.setImageBitmap(bitmap);
  21. mDoubleCache.put(url,bitmap);
  22. return;
  23. }
  24. submitLoadRequest(url, imageView);
  25. }
  26. private void submitLoadRequest(final String url, final ImageView imageView) {
  27. Log.i(TAG,"Download,url:"+url);
  28. imageView.setTag(url);
  29. mExecutorService.submit(new Runnable() {
  30. @Override
  31. public void run() {
  32. final Bitmap bitmap = downloadImage(url);
  33. if (imageView.getTag().equals(url)) {
  34. imageView.post(new Runnable() {
  35. @Override
  36. public void run() {
  37. imageView.setImageBitmap(bitmap);
  38. }
  39. });
  40. }
  41. mDoubleCache.put(url, bitmap);
  42. }
  43. });
  44. }
  45. Handler handler = new Handler(){
  46. @Override
  47. public void handleMessage(Message msg) {
  48. }
  49. };
  50. public Bitmap downloadImage(String url) {
  51. Bitmap bitmap = null;
  52. HttpURLConnection conn = null;
  53. try {
  54. URL url1 = new URL(url);
  55. conn = (HttpURLConnection) url1.openConnection();
  56. bitmap = BitmapFactory.decodeStream(conn.getInputStream());
  57. if (bitmap!=null){
  58. mDoubleCache.put(url,bitmap);
  59. }
  60. } catch (MalformedURLException e) {
  61. e.printStackTrace();
  62. } catch (Exception e) {
  63. e.printStackTrace();
  64. } finally {
  65. if (conn != null) {
  66. conn.disconnect();
  67. }
  68. }
  69. return bitmap;
  70. }

[java] view
plain
copy

  1. displayImage()

方法中能够看到。假设缓存中都没有才从网络中获取

[java] view
plain
copy

  1. public Bitmap downloadImage(String url) {}

下载完毕之后。把图片放到缓存中。

到这里,我们的第二张流程图就走完了。是不是非常easy。

我们在看一下是怎样使用的

[java] view
plain
copy

  1. private ImageView imageView;
  2. private ImageView imageView2;
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. setContentView(R.layout.activity_main);
  7. imageView = (ImageView) findViewById(R.id.image);
  8. imageView2 = (ImageView) findViewById(R.id.image2);
  9. imageView.setOnClickListener(new View.OnClickListener() {
  10. @Override
  11. public void onClick(View v) {
  12. ImageLoader.getInstance(MainActivity.this).displayImage("http://img.my.csdn.net/uploads/201407/26/1406383299_1976.jpg", imageView);
  13. }
  14. });
  15. imageView2.setOnClickListener(new View.OnClickListener() {
  16. @Override
  17. public void onClick(View v) {
  18. ImageLoader.getInstance(MainActivity.this).displayImage("http://img.my.csdn.net/uploads/201407/26/1406383299_1976.jpg", imageView2);
  19. }
  20. });
  21. }

点击下载源代码

时间: 2024-10-10 14:02:28

Android图片二级缓存的相关文章

毕加索的艺术——Picasso,一个强大的Android图片下载缓存库,OkHttpUtils的使用,二次封装PicassoUtils实现微信精选

毕加索的艺术--Picasso,一个强大的Android图片下载缓存库,OkHttpUtils的使用,二次封装PicassoUtils实现微信精选 官网: http://square.github.io/picasso/ 我们在上篇OkHttp的时候说过这个Picasso,学名毕加索,是Square公司开源的一个Android图形缓存库,而且使用起来也是非常的简单,只要一行代码就轻松搞定了,你会问,为什么不介绍一下Glide?其实Glide我有时间也是会介绍的,刚好上篇我们用到了Picasso,

【第六篇】Volley代码修改之图片二级缓存以及相关源码阅读(重现ImageLoader.ImageCache)

前面http://www.cnblogs.com/androidsuperman/p/8a157b18ede85caa61ca5bc04bba43d0.html 有讲到使用LRU来处理缓存的,但是只是处理内存里面的缓存,没进行文件缓存和处理,那么如何实现Volley在本地的缓存呢 一般硬盘缓存使用com.jakewharton.disklrucache.DiskLruCache这个Lru缓存,具体代码在 https://github.com/JakeWharton/DiskLruCache/tr

picasso-强大的Android图片下载缓存库

编辑推荐:稀土掘金,这是一个针对技术开发者的一个应用,你可以在掘金上获取最新最优质的技术干货,不仅仅是Android知识.前端.后端以至于产品和设计都有涉猎,想成为全栈工程师的朋友不要错过! picasso是Square公司开源的一个Android图形缓存库,地址http://square.github.io/picasso/,可以实现图片下载和缓存功能.仅仅只需要一行代码就能完全实现图片的异步加载: Picasso.with(context).load("http://i.imgur.com/

picasso_强大的Android图片下载缓存库

picasso是Square公司开源的一个Android图形缓存库,地址http://square.github.io/picasso/,可以实现图片下载和缓存功能.仅仅只需要一行代码就能完全实现图片的异步加载: 1 Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView); Api看起来非常独特,是吧. Picasso不仅实现了图片异步加载的功能,还解决了android中加载图片时需要解决

SDWebImage图片二级缓存异步加载基本原理

关于SDWebImage SDWebImage是一个针对图片加载的插件库,提供了一个支持缓存的用于异步加载图片的下载工具,特别的为常用的UI元素:UIImageView,UIButton和MKAnnotationView提供了Category类别扩展,可以作为一个很方便的工具.其中SDWebImagePrefetcher可以预先下载图片,方便后续使用. SDWebImage的Github地址为:https://github.com/rs/SDWebImage SDWebImage的几点特性 为U

android图片的缓存--节约内存提高程序效率

现在android应用占内存一个比一个大,android程序的质量亟待提高. 这里简单说说网络图片的缓存,我这边就简单的说说思路 1:网络图片,无疑需要去下载图片,我们不需要每次都去下载. 维护一张表,表里面放url 对应 存储的文件名 实现方法就是先拿到要下载的url,拿这个url去数据库匹配,如果有这张图片,那就不需要重新去下载了,直接通过数据库,去拿到图片的位置,然后从本地把图片加载出来就OK了.没有这张图片的时候去下载一下,并且存一下数据库 好处:这么做的好处很明显,下载过的图片不需要重

Android图片三级缓存策略

1.简介 Android缓存原理都是一样,可以自己封装. 三级缓存: 1.内存缓存:缓存在内存中,基于LRU(least recently used )算法,机器重启消失. 2.本地缓存.缓存在本地中.一般键值对形式.(url,filepath) 3.网络缓存.从网络加载资源,然后缓存在内存.本地中. 2.实现步骤 2.1 内存缓存: [java] view plain copypublic class MemoryCacheUtils { private LruCache<String,Bit

如何使用picasso 对Android图片下载缓存

相比较其他,picasso的图片缓存更加简单一些,他只需要一行代码就可以表述:导入相关jar包 Picasso.with(context).load("图片路径").into(ImageView控件); listView加载图片,在现在的app中都是非常常见的,我们往往要处理图片加载缓慢,错位等常见问题.Picasso不仅实现了图片的异步加载,同时对一些问题也做了解决和优化 比如:1.当在listView,滑动的时候,我们需要在adapter中把已经不再视野的ImageView图片资源

Android 图片三级缓存加载框架原理解析与代码实现

本文主要介绍三级缓存的原理解析与实现方式.以前一直觉得三级缓存图片加载是一个很难理解的东西,但是自己看了一下午再试着写了一遍之后感觉还是只要沉下心思考还时很容易熟悉掌握的. 所谓三级缓存:首先是内存-文件(外存)-网络三级缓存机制. 首先: 框架需要一个接入方法NGImageloadHelper.java: /** * 图片加载框架使用帮助类 * Created by nangua on 2016/7/8. */ public class NGImageloadHelper { /** * 处理