android 新闻图片加载,缓存处理

来源:互联网 发布:ubuntu tar 解压命令 编辑:程序博客网 时间:2024/05/22 09:00

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

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

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

我们先分开讲解

方法一:网络下载

方法二:从本地文件加载

方法三:从缓存中读取


先来说方法一:

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

直接上代码

//网络获取图片   protected Bitmap getNetBitmapByURL(String urlString) {URL url = null;InputStream inputStream = null;HttpURLConnection urlConnection = null;Bitmap bmp = null;try {url = new URL(urlString);urlConnection = (HttpURLConnection) url.openConnection();urlConnection.setRequestMethod("GET");urlConnection.setConnectTimeout(10000);inputStream = urlConnection.getInputStream();byte[] bt = getBytesFromStream(inputStream);bmp = BitmapFactory.decodeByteArray(bt, 0, bt.length);} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {if (null != inputStream) {try {inputStream.close();inputStream = null;} catch (IOException e) {e.printStackTrace();}}if (null != urlConnection) {urlConnection.disconnect();urlConnection = null;}}return bmp;}// 数据流private byte[] getBytesFromStream(InputStream inputStream) {ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] b = new byte[1024];int len = 0;while (len != -1) {try {len = inputStream.read(b);} catch (IOException e) {e.printStackTrace();}if (len != -1) {baos.write(b, 0, len); }}if (inputStream != null) {try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}return baos.toByteArray();}
这个地方获取了Bitmap  用handler呈现就很好搞定


再来说方法二本地获取:

直接根据图片路径获取Bitmap


private boolean cacheBmpToMemory(File file) {boolean sucessed = true;InputStream inputStream = null;try {inputStream = new FileInputStream(file);} catch (FileNotFoundException e) {e.printStackTrace();sucessed = false;}byte[] bs = getBytesFromStream(inputStream);Bitmap bitmap = BitmapFactory.decodeByteArray(bs, 0, bs.length);if (bitmap == null) {return null;}return bitmap;}private byte[] getBytesFromStream(InputStream inputStream) {boolean b2 = true;ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] b = new byte[1024];int len = 0;while (len != -1 && b2) {try {len = inputStream.read(b);if (len != -1) {baos.write(b, 0, len);}} catch (IOException e) {b2 = false;try {inputStream.close();} catch (IOException e1) {}}}if (inputStream != null) {try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}return baos.toByteArray();}




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


java文件:

ImageCache.java

package com.imageService;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.WeakHashMap;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Bitmap.CompressFormat;import android.os.Environment;public class ImageCache extends WeakHashMap<String, Bitmap> {private static ImageCache mNetImageViewCache = new ImageCache();private static final String CACHE_FILE = "/Cache";private ImageCache() {}public static ImageCache getInstance() {return mNetImageViewCache;}/** * 判断图片是否存在首先判断内存中是否存在然后判断本地是否存在 *  * @param url * @return */public boolean isBitmapExit(String url) {boolean isExit = containsKey(url);if (false == isExit) {isExit = isLocalHasBmp(url);}return isExit;}/* * 判断本地有没有 */private boolean isLocalHasBmp(String url) {boolean isExit = true;String name = changeUrlToName(url);String filePath = isCacheFileIsExit();File file = new File(filePath, name);if (file.exists()) {isExit = cacheBmpToMemory(file, url);} else {isExit = false;}return isExit;}/* * 将本地图片缓存到内存中 */private boolean cacheBmpToMemory(File file, String url) {boolean sucessed = true;InputStream inputStream = null;try {inputStream = new FileInputStream(file);} catch (FileNotFoundException e) {e.printStackTrace();sucessed = false;}byte[] bs = getBytesFromStream(inputStream);Bitmap bitmap = BitmapFactory.decodeByteArray(bs, 0, bs.length);if (bitmap == null) {return false;}this.put(url, bitmap, false);return sucessed;}private byte[] getBytesFromStream(InputStream inputStream) {boolean b2 = true;ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] b = new byte[1024];int len = 0;while (len != -1 && b2) {try {len = inputStream.read(b);if (len != -1) {baos.write(b, 0, len);}} catch (IOException e) {b2 = false;try {inputStream.close();} catch (IOException e1) {}}}if (inputStream != null) {try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}return baos.toByteArray();}/* * 判断缓存文件夹是否存在如果存在怎返回文件夹路径,如果不存在新建文件夹并返回文件夹路径 */private String isCacheFileIsExit() {String filePath = "";String rootpath = "";if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {rootpath = Environment.getExternalStorageDirectory().toString();}filePath = rootpath + CACHE_FILE;File file = new File(filePath);if (!file.exists()) {file.mkdirs();}return filePath;}/* * 将url变成图片的地址 */private String changeUrlToName(String url) {String name = url.replaceAll(":", "_");name = name.replaceAll("//", "_");name = name.replaceAll("/", "_");name = name.replaceAll("=", "_");name = name.replaceAll(",", "_");name = name.replaceAll("&", "_");return name;}public Bitmap put(String key, Bitmap value) {String filePath = isCacheFileIsExit();String name = changeUrlToName(key);File file = new File(filePath, name);OutputStream outputStream = null;try {outputStream = new FileOutputStream(file);value.compress(CompressFormat.JPEG, 100, outputStream);} catch (FileNotFoundException e) {e.printStackTrace();}try {if (null != outputStream)outputStream.flush();} catch (IOException e1) {e1.printStackTrace();}try {if (null != outputStream)outputStream.flush();} catch (IOException e) {e.printStackTrace();}if (null != outputStream) {try {outputStream.close();} catch (IOException e) {e.printStackTrace();}outputStream = null;}return super.put(key, value);}/** *  * @param key * @param value * @param isCacheToLocal *            是否缓存到本地 * @return */public Bitmap put(String key, Bitmap value, boolean isCacheToLocal) {if (isCacheToLocal) {return this.put(key, value);} else {return super.put(key, value);}}}

ImageService.java


package com.imageService;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.lang.ref.SoftReference;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.util.HashMap;import java.util.Map;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Handler;import android.os.Message;import android.util.Log;import android.widget.ImageView;/** * @author jingche.yhq 使用说明:1.先增加权限:    <uses-permission android:name="android.permission.INTERNET" />    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />    2.图片URL和ImageView直接输入函数    EX:    ImageService imageService = new ImageService(this);    ImageView imageView;    imageService.setBitmapByURL2("http://i1.itc.cn/20120801/a75_b0e447db_3573_ab5c_2058_5845d13545b9_1.jpg", imageView,defaultBitmap); */public class ImageService {//*********************************************线程池获取图片资源******************************************************//本地数据缓存public Map<String, SoftReference<Bitmap>> imageCacheMap = new HashMap<String, SoftReference<Bitmap>>();//固定五个线程来执行任务    private ExecutorService executorService = Executors.newFixedThreadPool(5);    //回调函数使用 final static ImageService imageService = new ImageService();    public static ImageService getInstance(){return imageService;}/** * 将图片放进缓存,图片名称是由URL去掉一些符号得到 *  * @param url *            地址 * @param bitmap *            图片 */public void putImageCache(String url, Bitmap bitmap) {try {if(!ImageCache.getInstance().isBitmapExit(url));ImageCache.getInstance().put(url, bitmap, true);} catch (Exception e) {e.printStackTrace();}}/** *  * @param url图片URL  *  * @param imageView imageView *  * @param defaultBitmap 获取图片失败这显示默认图片 */public void setBitmapByURL(String url,final ImageView imageView,final Bitmap defaultBitmap,boolean isCacheToLocal) {//采用Handler+Thread+封装外部接口    //如果缓存过就会从缓存中取出图像,ImageCallback接口中方法也不会被执行Bitmap cacheImage = loadBitmap(url,imageView,isCacheToLocal,new ImageCallback() {    //请参见实现:如果第一次加载URL时下面方法会执行@Overridepublic void imageLoad(ImageView imageView, Bitmap bitmap) {//如果返回的Bitmap为空这选择默认图片       if (bitmap!=null) {            imageView.setImageBitmap(bitmap);       }else {       imageView.setImageBitmap(defaultBitmap);       }}     });     if(cacheImage!=null){     imageView.setImageBitmap(cacheImage);     }else {    // imageView.setImageBitmap(defaultBitmap);}} /**    *    * @param imageUrl     图像URL地址    * @param imageCallback     回调接口    * @return     返回内存中缓存的图像,第一次加载返回null    */   public Bitmap loadBitmap(final String imageUrl,final ImageView imageView,final boolean isCacheToLocal,final ImageCallback imageCallback) {       //如果缓存过就从缓存中取出数据   final Handler handler = new Handler()         {             @Override             public void handleMessage(Message msg)             {             imageCallback.imageLoad(imageView, (Bitmap)msg.obj);             }         };         if (imageCacheMap.containsKey(imageUrl)) {       Log.e("提示", "缓存获取图片");           SoftReference<Bitmap> softReference = imageCacheMap.get(imageUrl);           if (softReference.get() != null) {               return softReference.get();           }       }else            if(ImageCache.getInstance().isBitmapExit(imageUrl)){       Log.e("提示", "本地获取图片");       Bitmap bitmap=null;       try {bitmap = ImageCache.getInstance().get(imageUrl);} catch (Exception e) {bitmap = null;}return bitmap;       }       else {       //缓存中没有图像,则从网络上取出数据,并将取出的数据缓存到内存中        executorService.submit(new Runnable() {           public void run() {               try {               //获取图片                   final Bitmap bitmap = getNetBitmapByURL(imageUrl);                   //将图片放置到内存中                   Log.e("提示", "网络获取图片"+Thread.currentThread().getName());                   if(bitmap!=null){                   Log.e("提示", "存储图");                   imageCacheMap.put(imageUrl, new SoftReference<Bitmap>(bitmap));                   ImageCache.getInstance().put(imageUrl, bitmap, isCacheToLocal);                   }                   Message msg = handler.obtainMessage(0, bitmap);                     handler.sendMessage(msg);               } catch (Exception e) {                   throw new RuntimeException(e);               }           }       });       }       return null;   }   //网络获取图片   protected Bitmap getNetBitmapByURL(String urlString) {URL url = null;InputStream inputStream = null;HttpURLConnection urlConnection = null;Bitmap bmp = null;try {url = new URL(urlString);urlConnection = (HttpURLConnection) url.openConnection();urlConnection.setRequestMethod("GET");urlConnection.setConnectTimeout(10000);inputStream = urlConnection.getInputStream();byte[] bt = getBytesFromStream(inputStream);bmp = BitmapFactory.decodeByteArray(bt, 0, bt.length);} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {if (null != inputStream) {try {inputStream.close();inputStream = null;} catch (IOException e) {e.printStackTrace();}}if (null != urlConnection) {urlConnection.disconnect();urlConnection = null;}}return bmp;}// 数据流private byte[] getBytesFromStream(InputStream inputStream) {ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] b = new byte[1024];int len = 0;while (len != -1) {try {len = inputStream.read(b);} catch (IOException e) {e.printStackTrace();}if (len != -1) {baos.write(b, 0, len); }}if (inputStream != null) {try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}return baos.toByteArray();}   //对外界开放的回调接口   private interface ImageCallback {       //注意 此方法是用来设置目标对象的图像资源   public void imageLoad(ImageView imageView, Bitmap bitmap);   }   }


test


public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);                ImageService imageService = new ImageService();        ImageView imageView = (ImageView)findViewById(R.id.imageView1);       imageService.setBitmapByURL("http://i1.itc.cn/20120801/a75_b0e447db_3573_ab5c_2058_5845d13545b9_1.jpg", imageView,BitmapFactory.decodeResource(getResources(), R.drawable.icon));    }


呵呵!很多不足,欢迎拍砖哈。