zoukankan      html  css  js  c++  java
  • Android图片二级缓存

    点击下载源代码

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

    当时的思路是这种


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

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

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

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


    那我们从第一部開始解析

    1.先看 内存缓存的代码

    [java] view plaincopy
    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.   
    8.     private void init(){  
    9.         final int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024);  
    10.         final int cacheSize = maxMemory/4;  
    11.         mMemoryCache = new LruCache<String,Bitmap>(cacheSize){  
    12.             @Override  
    13.             protected int sizeOf(String key, Bitmap value) {  
    14.                 return value.getRowBytes()*value.getHeight()/1024;  
    15.             }  
    16.         };  
    17.     }  
    18.     @Override  
    19.     public Bitmap get(String key) {  
    20.         Bitmap bitmap = mMemoryCache.get(key);  
    21.         if (bitmap!=null){  
    22.             Log.i(TAG,"File is exist in memory");  
    23.         }  
    24.         return mMemoryCache.get(key);  
    25.     }  
    26.   
    27.     @Override  
    28.     public void put(String key, Bitmap bitmap) {  
    29.         if (get(key)==null) {  
    30.             mMemoryCache.put(key, bitmap);  
    31.         }  
    32.     }  
    33. }  


    [java] view plaincopy
    1. private void init()  
    init()方法中对一些变量进行初始化,mMemoryCache用于在内存中缓存图片

    [java] view plaincopy
    1. public Bitmap get(String key) {}  

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

    [java] view plaincopy
    1. public void put(String key, Bitmap bitmap) {}  
    put()方法将下载好的图片缓存到内存中,方便下次使用


    2.再看sd卡缓存

    [java] view plaincopy
    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.   
    24.     @Override  
    25.     public void put(String key, Bitmap bitmap) {  
    26.         FileOutputStream fileOutputStream = null;  
    27.         try {  
    28.             File file = new File(mPath+key);  
    29.             if (file.exists()){  
    30.                 Log.i(TAG,"File is exist on disk");  
    31.             }  
    32.             fileOutputStream = new FileOutputStream(mPath+key);  
    33.             bitmap.compress(Bitmap.CompressFormat.PNG,100,fileOutputStream);  
    34.   
    35.         } catch (FileNotFoundException e) {  
    36.             e.printStackTrace();  
    37.         }finally {  
    38.             CloseUtils.closeQuietly(fileOutputStream);  
    39.         }  
    40.     }  
    41.   
    42.     /** 
    43.      * 依据传入的dir获得路径 
    44.      * @param context 
    45.      * @param dir 
    46.      * @return 
    47.      */  
    48.     public String getDiskCachePath(Context context, String dir) {  
    49.         String cachePath;  
    50.         if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())  
    51.                 || !Environment.isExternalStorageRemovable()) {  
    52.             cachePath = context.getExternalCacheDir().getPath();  
    53.         } else {  
    54.             cachePath = context.getCacheDir().getPath();  
    55.         }  
    56.         return cachePath + File.separator + dir;  
    57.     }  
    58.   
    59. }  
    相同

    [java] view plaincopy
    1. private void init()  
    init()方法中对一些变量进行初始化,mMemoryCache用于在内存中缓存图片

    [java] view plaincopy
    1. public Bitmap get(String key) {}  

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

    [java] view plaincopy
    1. public void put(String key, Bitmap bitmap) {}  
    put()方法将下载好的图片缓存到内存中,方便下次使用

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

    [java] view plaincopy
    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.   
    6.     public DoubleCache(Context context){  
    7.         mMemoryCache = new MemoryCache();  
    8.         mDiskCache = new DiskCache(context);  
    9.     }  
    10.     @Override  
    11.     public Bitmap get(String url) {  
    12.         String key = url2Key(url);  
    13.         Bitmap bitmap = mMemoryCache.get(key);  
    14.         if(bitmap==null){  
    15.             bitmap = mDiskCache.get(key);  
    16.         }else {  
    17.         }  
    18.         return bitmap;  
    19.      }  
    20.   
    21.     @Override  
    22.     public void put(String url, Bitmap bitmap) {  
    23.         String key = url2Key(url);  
    24.         mMemoryCache.put(key,bitmap);  
    25.         mDiskCache.put(key,bitmap);  
    26.     }  
    27.   
    28.     //url转key  
    29.     private String url2Key(String url){  
    30.         String key = MD5.hashKeyForDisk(url)+".jpg";  
    31.         return key;  
    32.     }  
    33. }  
    我们在获取缓存的时候先从内存中获取。当内存中击中直接返回,当内存中没有击中,则訪问sd卡。

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

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

    [java] view plaincopy
    1. displayImage()  
    方法中能够看到。假设缓存中都没有才从网络中获取

    [java] view plaincopy
    1. public Bitmap downloadImage(String url) {}  
    下载完毕之后。把图片放到缓存中。

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

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

    [java] view plaincopy
    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.   
    13.             ImageLoader.getInstance(MainActivity.this).displayImage("http://img.my.csdn.net/uploads/201407/26/1406383299_1976.jpg", imageView);  
    14.         }  
    15.     });  
    16.     imageView2.setOnClickListener(new View.OnClickListener() {  
    17.         @Override  
    18.         public void onClick(View v) {  
    19.   
    20.             ImageLoader.getInstance(MainActivity.this).displayImage("http://img.my.csdn.net/uploads/201407/26/1406383299_1976.jpg", imageView2);  
    21.         }  
    22.     });  
    23. }  


    点击下载源代码

  • 相关阅读:
    PAT (Basic Level) Practise 1013 数素数
    PAT (Basic Level) Practise 1014 福尔摩斯的约会
    codeforces 814B.An express train to reveries 解题报告
    KMP算法
    rsync工具
    codeforces 777C.Alyona and Spreadsheet 解题报告
    codeforces 798C.Mike and gcd problem 解题报告
    nginx + tomcat多实例
    MongoDB副本集
    指针的艺术(转载)
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/7291116.html
Copyright © 2011-2022 走看看