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

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

一般我们写的过程中是这么处理的:先去缓存(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));    }


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




更多相关文章

  1. Android(安卓)图片获取及上传
  2. 使用Glide替换Picasso经验小结
  3. android正在运行进程和后台缓存进程的区别
  4. Android中新建的文件在R没有显示对应的文件解决办法总结
  5. Android多点触控实现图片缩放预览
  6. android 的外部存储的挂载的理解
  7. Android(安卓)分享功能之 微信 图片分享
  8. Android(安卓)Volley完全解析(四),带你从源码的角度理解Volley
  9. Android创建应用快捷方式(ShortCut)的有效方式

随机推荐

  1. 物联网时代安防行业(包含信息安全行业)所面
  2. 如何用Redis实现分布式锁以及可用性
  3. 关于技术管理(不定时更新)
  4. zookeeper分布式锁
  5. ab测试工具的使用
  6. docker-compose安装Harbor
  7. 关于动态通知类的推拉模式
  8. 关于jar打包分块
  9. js基础知识:图片懒加载及导航图手动轮播、
  10. 【php基础入门】PHP环境搭建与初识php代