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. }  


    点击下载源代码

  • 相关阅读:
    用电脑给手机安装App
    切换皮肤的实现
    瀑布流的简单实现
    HTML5的实用
    HTML5的特性,发展,及使用
    录音的使用步骤
    支付宝集成步骤
    美团(iPad)顶部界面的简单实现, 及开发时常见bug
    真机调试/打包测试/程序发布/内购的具体操作流程
    IOS 触摸事件的处理
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/7291116.html
Copyright © 2011-2022 走看看