Android学习之路-------复习一下缓存和读取缓存,网络加载图片

来源:互联网 发布:大数据涂子沛概括 编辑:程序博客网 时间:2024/06/05 15:33

在开发中,遇到很多大量图片呈现给用户,那么我们怎么又快又高效的显示给用户呢?

在这里结合前人写的文章和自己的一些改动。

一般我们写的过程中是这么处理的:先去缓存(WeakHashMap<String, Bitmap>来存储图片)中提取,这样速度快又节约流量,缓存中没有再选择本地有图片没有,如果两者都没有则只有从网络去获取。

我们先分开讲解

方法一:网络下载

方法二:从本地文件加载

方法三:从缓存中读取


先来说方法一:

加载很多图片的时候,我们经常用多线程在后台下载,在handler中将图片呈现在界面。

直接上代码

[java] view plain copy
  1. //网络获取图片  
  2.    protected Bitmap getNetBitmapByURL(String urlString) {  
  3.         URL url = null;  
  4.         InputStream inputStream = null;  
  5.         HttpURLConnection urlConnection = null;  
  6.         Bitmap bmp = null;  
  7.         try {  
  8.             url = new URL(urlString);  
  9.             urlConnection = (HttpURLConnection) url.openConnection();  
  10.             urlConnection.setRequestMethod("GET");  
  11.             urlConnection.setConnectTimeout(10000);  
  12.             inputStream = urlConnection.getInputStream();  
  13.             byte[] bt = getBytesFromStream(inputStream);  
  14.             bmp = BitmapFactory.decodeByteArray(bt, 0, bt.length);  
  15.         } catch (MalformedURLException e) {  
  16.             e.printStackTrace();  
  17.         } catch (IOException e) {  
  18.             e.printStackTrace();  
  19.         } finally {  
  20.             if (null != inputStream) {  
  21.                 try {  
  22.                     inputStream.close();  
  23.                     inputStream = null;  
  24.                 } catch (IOException e) {  
  25.                     e.printStackTrace();  
  26.                 }  
  27.             }  
  28.             if (null != urlConnection) {  
  29.                 urlConnection.disconnect();  
  30.                 urlConnection = null;  
  31.             }  
  32.         }  
  33.         return bmp;  
  34.     }  
  35.   
  36.     // 数据流  
  37.     private byte[] getBytesFromStream(InputStream inputStream) {  
  38.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  39.         byte[] b = new byte[1024];  
  40.         int len = 0;  
  41.         while (len != -1) {  
  42.             try {  
  43.                 len = inputStream.read(b);  
  44.             } catch (IOException e) {  
  45.                 e.printStackTrace();  
  46.             }  
  47.             if (len != -1) {  
  48.                 baos.write(b, 0, len);   
  49.             }  
  50.         }  
  51.         if (inputStream != null) {  
  52.             try {  
  53.                 inputStream.close();  
  54.             } catch (IOException e) {  
  55.                 e.printStackTrace();  
  56.             }  
  57.         }  
  58.         return baos.toByteArray();  
  59.     }  
这个地方获取了Bitmap  用handler呈现就很好搞定


再来说方法二本地获取:

直接根据图片路径获取Bitmap


[java] view plain copy
  1. private boolean cacheBmpToMemory(File file) {  
  2.         boolean sucessed = true;  
  3.         InputStream inputStream = null;  
  4.         try {  
  5.             inputStream = new FileInputStream(file);  
  6.         } catch (FileNotFoundException e) {  
  7.             e.printStackTrace();  
  8.             sucessed = false;  
  9.         }  
  10.         byte[] bs = getBytesFromStream(inputStream);  
  11.         Bitmap bitmap = BitmapFactory.decodeByteArray(bs, 0, bs.length);  
  12.         if (bitmap == null) {  
  13.             return null;  
  14.         }  
  15.         return bitmap;  
  16.     }  
  17. private byte[] getBytesFromStream(InputStream inputStream) {  
  18.         boolean b2 = true;  
  19.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  20.         byte[] b = new byte[1024];  
  21.         int len = 0;  
  22.         while (len != -1 && b2) {  
  23.             try {  
  24.                 len = inputStream.read(b);  
  25.                 if (len != -1) {  
  26.                     baos.write(b, 0, len);  
  27.                 }  
  28.             } catch (IOException e) {  
  29.                 b2 = false;  
  30.                 try {  
  31.                     inputStream.close();  
  32.                 } catch (IOException e1) {  
  33.                 }  
  34.             }  
  35.   
  36.         }  
  37.   
  38.         if (inputStream != null) {  
  39.             try {  
  40.                 inputStream.close();  
  41.             } catch (IOException e) {  
  42.                 e.printStackTrace();  
  43.             }  
  44.         }  
  45.         return baos.toByteArray();  
  46.     }  




方法三缓存获取:
用弱引用:WeakHashMap<String, Bitmap>,以弱键 实现的基于哈希表的 Map,在 WeakHashMap 中,当某个键不再正常使用时,将自动移除其条目。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。丢弃某个键时,其条目从映射中有效地移除。
WeakHashMap 中的每个键对象间接地存储为一个弱引用的指示对象。因此,不管是在映射内还是在映射之外,只有在垃圾回收器清除某个键的弱引用之后,该键才会自动移除
这个地方结合方法一和方法二,写了一个有关图片缓存的解决方法。


Java文件:

ImageCache.java

[java] view plain copy
  1. package com.imageService;  
  2.   
  3. import java.io.ByteArrayOutputStream;  
  4. import java.io.File;  
  5. import java.io.FileInputStream;  
  6. import java.io.FileNotFoundException;  
  7. import java.io.FileOutputStream;  
  8. import java.io.IOException;  
  9. import java.io.InputStream;  
  10. import java.io.OutputStream;  
  11. import java.util.WeakHashMap;  
  12.   
  13. import android.graphics.Bitmap;  
  14. import android.graphics.BitmapFactory;  
  15. import android.graphics.Bitmap.CompressFormat;  
  16. import android.os.Environment;  
  17.   
  18.   
  19. public class ImageCache extends WeakHashMap<String, Bitmap> {  
  20.   
  21.     private static ImageCache mNetImageViewCache = new ImageCache();  
  22.     private static final String CACHE_FILE = "/Cache";  
  23.   
  24.     private ImageCache() {  
  25.   
  26.     }  
  27.   
  28.     public static ImageCache getInstance() {  
  29.         return mNetImageViewCache;  
  30.     }  
  31.   
  32.     /** 
  33.      * 判断图片是否存在首先判断内存中是否存在然后判断本地是否存在 
  34.      *  
  35.      * @param url 
  36.      * @return 
  37.      */  
  38.     public boolean isBitmapExit(String url) {  
  39.         boolean isExit = containsKey(url);  
  40.         if (false == isExit) {  
  41.             isExit = isLocalHasBmp(url);  
  42.         }  
  43.         return isExit;  
  44.     }  
  45.   
  46.     /* 
  47.      * 判断本地有没有 
  48.      */  
  49.     private boolean isLocalHasBmp(String url) {  
  50.         boolean isExit = true;  
  51.   
  52.         String name = changeUrlToName(url);  
  53.         String filePath = isCacheFileIsExit();  
  54.   
  55.         File file = new File(filePath, name);  
  56.   
  57.         if (file.exists()) {  
  58.             isExit = cacheBmpToMemory(file, url);  
  59.         } else {  
  60.             isExit = false;  
  61.         }  
  62.         return isExit;  
  63.     }  
  64.   
  65.     /* 
  66.      * 将本地图片缓存到内存中 
  67.      */  
  68.     private boolean cacheBmpToMemory(File file, String url) {  
  69.         boolean sucessed = true;  
  70.         InputStream inputStream = null;  
  71.         try {  
  72.             inputStream = new FileInputStream(file);  
  73.         } catch (FileNotFoundException e) {  
  74.             e.printStackTrace();  
  75.             sucessed = false;  
  76.         }  
  77.         byte[] bs = getBytesFromStream(inputStream);  
  78.         Bitmap bitmap = BitmapFactory.decodeByteArray(bs, 0, bs.length);  
  79.         if (bitmap == null) {  
  80.             return false;  
  81.         }  
  82.         this.put(url, bitmap, false);  
  83.         return sucessed;  
  84.     }  
  85.   
  86.     private byte[] getBytesFromStream(InputStream inputStream) {  
  87.         boolean b2 = true;  
  88.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  89.         byte[] b = new byte[1024];  
  90.         int len = 0;  
  91.         while (len != -1 && b2) {  
  92.             try {  
  93.                 len = inputStream.read(b);  
  94.                 if (len != -1) {  
  95.                     baos.write(b, 0, len);  
  96.                 }  
  97.             } catch (IOException e) {  
  98.                 b2 = false;  
  99.                 try {  
  100.                     inputStream.close();  
  101.                 } catch (IOException e1) {  
  102.                 }  
  103.             }  
  104.   
  105.         }  
  106.   
  107.         if (inputStream != null) {  
  108.             try {  
  109.                 inputStream.close();  
  110.             } catch (IOException e) {  
  111.                 e.printStackTrace();  
  112.             }  
  113.         }  
  114.         return baos.toByteArray();  
  115.     }  
  116.   
  117.     /* 
  118.      * 判断缓存文件夹是否存在如果存在怎返回文件夹路径,如果不存在新建文件夹并返回文件夹路径 
  119.      */  
  120.     private String isCacheFileIsExit() {  
  121.         String filePath = "";  
  122.         String rootpath = "";  
  123.   
  124.         if (Environment.getExternalStorageState().equals(  
  125.                 Environment.MEDIA_MOUNTED)) {  
  126.             rootpath = Environment.getExternalStorageDirectory().toString();  
  127.         }  
  128.         filePath = rootpath + CACHE_FILE;  
  129.         File file = new File(filePath);  
  130.         if (!file.exists()) {  
  131.             file.mkdirs();  
  132.         }  
  133.         return filePath;  
  134.     }  
  135.   
  136.     /* 
  137.      * 将url变成图片的地址 
  138.      */  
  139.     private String changeUrlToName(String url) {  
  140.         String name = url.replaceAll(":""_");  
  141.         name = name.replaceAll("//""_");  
  142.         name = name.replaceAll("/""_");  
  143.         name = name.replaceAll("=""_");  
  144.         name = name.replaceAll(",""_");  
  145.         name = name.replaceAll("&""_");  
  146.         return name;  
  147.     }  
  148.   
  149.     public Bitmap put(String key, Bitmap value) {  
  150.         String filePath = isCacheFileIsExit();  
  151.         String name = changeUrlToName(key);  
  152.         File file = new File(filePath, name);  
  153.         OutputStream outputStream = null;  
  154.         try {  
  155.             outputStream = new FileOutputStream(file);  
  156.             value.compress(CompressFormat.JPEG, 100, outputStream);  
  157.         } catch (FileNotFoundException e) {  
  158.             e.printStackTrace();  
  159.         }  
  160.         try {  
  161.             if (null != outputStream)  
  162.                 outputStream.flush();  
  163.         } catch (IOException e1) {  
  164.             e1.printStackTrace();  
  165.         }  
  166.         try {  
  167.             if (null != outputStream)  
  168.                 outputStream.flush();  
  169.         } catch (IOException e) {  
  170.             e.printStackTrace();  
  171.         }  
  172.         if (null != outputStream) {  
  173.             try {  
  174.                 outputStream.close();  
  175.             } catch (IOException e) {  
  176.                 e.printStackTrace();  
  177.             }  
  178.             outputStream = null;  
  179.         }  
  180.   
  181.         return super.put(key, value);  
  182.     }  
  183.   
  184.     /** 
  185.      *  
  186.      * @param key 
  187.      * @param value 
  188.      * @param isCacheToLocal 
  189.      *            是否缓存到本地 
  190.      * @return 
  191.      */  
  192.     public Bitmap put(String key, Bitmap value, boolean isCacheToLocal) {  
  193.         if (isCacheToLocal) {  
  194.             return this.put(key, value);  
  195.         } else {  
  196.             return super.put(key, value);  
  197.         }  
  198.     }  
  199. }  

ImageService.java


[java] view plain copy
  1. package com.imageService;  
  2.   
  3. import java.io.ByteArrayOutputStream;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.lang.ref.SoftReference;  
  7. import java.net.HttpURLConnection;  
  8. import java.net.MalformedURLException;  
  9. import java.net.URL;  
  10. import java.util.HashMap;  
  11. import java.util.Map;  
  12. import java.util.concurrent.ExecutorService;  
  13. import java.util.concurrent.Executors;  
  14.   
  15.   
  16. import android.graphics.Bitmap;  
  17. import android.graphics.BitmapFactory;  
  18. import android.os.Handler;  
  19. import android.os.Message;  
  20. import android.util.Log;  
  21. import android.widget.ImageView;  
  22. /** 
  23.  * @author jingche.yhq 
  24.  使用说明: 
  25.     1.先增加权限: 
  26.         <uses-permission android:name="android.permission.INTERNET" /> 
  27.         <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
  28.     2.图片URL和ImageView直接输入函数 
  29.     EX: 
  30.         ImageService imageService = new ImageService(this); 
  31.         ImageView imageView; 
  32.         imageService.setBitmapByURL2("http://i1.itc.cn/20120801/a75_b0e447db_3573_ab5c_2058_5845d13545b9_1.jpg", imageView,defaultBitmap); 
  33.  */  
  34. public class ImageService {  
  35.     //*********************************************线程池获取图片资源******************************************************  
  36.     //本地数据缓存  
  37.     public Map<String, SoftReference<Bitmap>> imageCacheMap = new HashMap<String, SoftReference<Bitmap>>();  
  38.     //固定五个线程来执行任务  
  39.     private ExecutorService executorService = Executors.newFixedThreadPool(5);  
  40.     //回调函数使用  
  41.   
  42.  final static ImageService imageService = new ImageService();  
  43.       
  44.     public static ImageService getInstance(){  
  45.         return imageService;  
  46.     }  
  47.     /**  
  48.      * 将图片放进缓存,图片名称是由URL去掉一些符号得到  
  49.      *   
  50.      * @param url  
  51.      *            地址  
  52.      * @param bitmap  
  53.      *            图片  
  54.      */  
  55.     public void putImageCache(String url, Bitmap bitmap) {  
  56.         try {  
  57.             if(!ImageCache.getInstance().isBitmapExit(url));  
  58.                 ImageCache.getInstance().put(url, bitmap, true);  
  59.         } catch (Exception e) {  
  60.             e.printStackTrace();  
  61.         }  
  62.     }  
  63.     /** 
  64.      *  
  65.      * @param url图片URL  
  66.      *  
  67.      * @param imageView imageView 
  68.      *  
  69.      * @param defaultBitmap 获取图片失败这显示默认图片 
  70.      */  
  71.     public void setBitmapByURL(String url,final ImageView imageView,final Bitmap defaultBitmap,boolean isCacheToLocal) {  
  72.         //采用Handler+Thread+封装外部接口  
  73.         //如果缓存过就会从缓存中取出图像,ImageCallback接口中方法也不会被执行  
  74.         Bitmap cacheImage = loadBitmap(url,imageView,isCacheToLocal,new ImageCallback() {  
  75.         //请参见实现:如果第一次加载URL时下面方法会执行  
  76.         @Override  
  77.         public void imageLoad(ImageView imageView, Bitmap bitmap) {  
  78.             //如果返回的Bitmap为空这选择默认图片  
  79.                if (bitmap!=null) {  
  80.                     imageView.setImageBitmap(bitmap);  
  81.                }else {  
  82.                    imageView.setImageBitmap(defaultBitmap);  
  83.                }  
  84.         }  
  85.          });  
  86.          if(cacheImage!=null){  
  87.              imageView.setImageBitmap(cacheImage);  
  88.          }else {  
  89.             // imageView.setImageBitmap(defaultBitmap);  
  90.         }  
  91.     }  
  92.      /** 
  93.     * 
  94.     * @param imageUrl     图像URL地址 
  95.     * @param imageCallback     回调接口 
  96.     * @return     返回内存中缓存的图像,第一次加载返回null 
  97.     */  
  98.    public Bitmap loadBitmap(final String imageUrl,final ImageView imageView,final boolean isCacheToLocal,final ImageCallback imageCallback) {  
  99.        //如果缓存过就从缓存中取出数据  
  100.        final Handler handler = new Handler()    
  101.        {    
  102.            @Override    
  103.            public void handleMessage(Message msg)    
  104.            {    
  105.                imageCallback.imageLoad(imageView, (Bitmap)msg.obj);    
  106.            }    
  107.        };    
  108.        if (imageCacheMap.containsKey(imageUrl)) {  
  109.            Log.e("提示""缓存获取图片");  
  110.            SoftReference<Bitmap> softReference = imageCacheMap.get(imageUrl);  
  111.            if (softReference.get() != null) {  
  112.                return softReference.get();  
  113.            }  
  114.        }else       
  115.        if(ImageCache.getInstance().isBitmapExit(imageUrl)){  
  116.            Log.e("提示""本地获取图片");  
  117.            Bitmap bitmap=null;  
  118.            try {  
  119.                 bitmap = ImageCache.getInstance().get(imageUrl);  
  120.             } catch (Exception e) {  
  121.                 bitmap = null;  
  122.             }  
  123.             return bitmap;  
  124.        }  
  125.        else {  
  126.           
  127.        //缓存中没有图像,则从网络上取出数据,并将取出的数据缓存到内存中  
  128.         executorService.submit(new Runnable() {  
  129.            public void run() {  
  130.                try {  
  131.                    //获取图片  
  132.                    final Bitmap bitmap = getNetBitmapByURL(imageUrl);  
  133.                    //将图片放置到内存中  
  134.                    Log.e("提示""网络获取图片"+Thread.currentThread().getName());  
  135.                    if(bitmap!=null){  
  136.                        Log.e("提示""存储图");  
  137.                        imageCacheMap.put(imageUrl, new SoftReference<Bitmap>(bitmap));  
  138.                        ImageCache.getInstance().put(imageUrl, bitmap, isCacheToLocal);  
  139.                    }  
  140.                    Message msg = handler.obtainMessage(0, bitmap);    
  141.                    handler.sendMessage(msg);  
  142.                } catch (Exception e) {  
  143.                    throw new RuntimeException(e);  
  144.                }  
  145.            }  
  146.        });  
  147.        }  
  148.        return null;  
  149.    }  
  150.    //网络获取图片  
  151.    protected Bitmap getNetBitmapByURL(String urlString) {  
  152.         URL url = null;  
  153.         InputStream inputStream = null;  
  154.         HttpURLConnection urlConnection = null;  
  155.         Bitmap bmp = null;  
  156.         try {  
  157.             url = new URL(urlString);  
  158.             urlConnection = (HttpURLConnection) url.openConnection();  
  159.             urlConnection.setRequestMethod("GET");  
  160.             urlConnection.setConnectTimeout(10000);  
  161.             inputStream = urlConnection.getInputStream();  
  162.             byte[] bt = getBytesFromStream(inputStream);  
  163.             bmp = BitmapFactory.decodeByteArray(bt, 0, bt.length);  
  164.         } catch (MalformedURLException e) {  
  165.             e.printStackTrace();  
  166.         } catch (IOException e) {  
  167.             e.printStackTrace();  
  168.         } finally {  
  169.             if (null != inputStream) {  
  170.                 try {  
  171.                     inputStream.close();  
  172.                     inputStream = null;  
  173.                 } catch (IOException e) {  
  174.                     e.printStackTrace();  
  175.                 }  
  176.             }  
  177.             if (null != urlConnection) {  
  178.                 urlConnection.disconnect();  
  179.                 urlConnection = null;  
  180.             }  
  181.         }  
  182.         return bmp;  
  183.     }  
  184.   
  185.     // 数据流  
  186.     private byte[] getBytesFromStream(InputStream inputStream) {  
  187.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  188.         byte[] b = new byte[1024];  
  189.         int len = 0;  
  190.         while (len != -1) {  
  191.             try {  
  192.                 len = inputStream.read(b);  
  193.             } catch (IOException e) {  
  194.                 e.printStackTrace();  
  195.             }  
  196.             if (len != -1) {  
  197.                 baos.write(b, 0, len);   
  198.             }  
  199.         }  
  200.         if (inputStream != null) {  
  201.             try {  
  202.                 inputStream.close();  
  203.             } catch (IOException e) {  
  204.                 e.printStackTrace();  
  205.             }  
  206.         }  
  207.         return baos.toByteArray();  
  208.     }  
  209.    //对外界开放的回调接口  
  210.    private interface ImageCallback {  
  211.        //注意 此方法是用来设置目标对象的图像资源  
  212.        public void imageLoad(ImageView imageView, Bitmap bitmap);  
  213.    }      
  214.      
  215. }  


test


[java] view plain copy
  1. public void onCreate(Bundle savedInstanceState) {  
  2.         super.onCreate(savedInstanceState);  
  3.         setContentView(R.layout.main);  
  4.           
  5.         ImageService imageService = new ImageService();  
  6.         ImageView imageView = (ImageView)findViewById(R.id.imageView1);  
  7.        imageService.setBitmapByURL("http://i1.itc.cn/20120801/a75_b0e447db_3573_ab5c_2058_5845d13545b9_1.jpg", imageView,BitmapFactory.decodeResource(getResources(), R.drawable.icon));  
  8.     }  
0 0