手机客户端以列表形式展示数据是非常常见的一种方式。然而列表中要显示图片(比如:头像)就要采用异步线程加载的方式,这样做是为了防止加载图片数据的时候,花费时间过长,阻塞UI线程,从而达到保持App的流畅性的目的。

下面我将分享 OSChina.NET Android版客户端的列表异步线程加载图片的方法:

图片缓存

private static HashMap<String, SoftReference<Bitmap>> cache;  

图片缓存是当有加载过相同的图片的时候,可以快速重复使用,比如同一个人的头像。

图片控件集合

private static Map<ImageView, String> imageViews;  

图片控件集合是一个Map,记录当前ImageView控件对应的图片地址,用来防止异步线程加载图片时候ImageView控件显示的图片与实际图片地址对应的图片不符,出现错乱。

线程池

private static ExecutorService pool;  

固定线程池里的并发线程数,可以防止用户在快速滑动列表的时候,不执行已经滑过去的加载线程。

具体的初始化代码:

static {  cache = new HashMap<String, SoftReference<Bitmap>>();  pool = Executors.newFixedThreadPool(5);  //固定线程池imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());}

接下来,我们来看看具体是如何加载图片的:

public void loadBitmap(String url, ImageView imageView, Bitmap defaultBmp, int width, int height) {  imageViews.put(imageView, url);  Bitmap bitmap = getBitmapFromCache(url);  if (bitmap != null) {  //显示缓存图片imageView.setImageBitmap(bitmap);  } else {  //加载SD卡中的图片缓存String filename = FileUtils.getFileName(url);String filepath = imageView.getContext().getFilesDir() + File.separator + filename;File file = new File(filepath);if(file.exists()){//显示SD卡中的图片缓存Bitmap bmp = ImageUtils.getBitmap(imageView.getContext(), filename);imageView.setImageBitmap(bmp);}else{//线程加载网络图片imageView.setImageBitmap(defaultBmp);queueJob(url, imageView, width, height);}}  }  

上面的代码中,我们根据图片的url地址,先从图片缓存里面查找是否已缓存过,如果没有,再从SD卡的图片缓存文件中查找,如果再没有,最后才是加载网络图片。这才是以最快速的方式显示图片。

下面,我将贴出完整的代码:

/*** 异步线程加载图片工具类* @author  liux*/
public class BitmapManager {  private static HashMap<String, SoftReference<Bitmap>> cache;  private static ExecutorService pool;  private static Map<ImageView, String> imageViews;  private Bitmap defaultBmp;  static {  cache = new HashMap<String, SoftReference<Bitmap>>();  pool = Executors.newFixedThreadPool(5);  //固定线程池imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());}  public BitmapManager(){}public BitmapManager(Bitmap def) {this.defaultBmp = def;}/*** 设置默认图片* @param bmp*/public void setDefaultBmp(Bitmap bmp) {  defaultBmp = bmp;  }   /*** 加载图片* @param url* @param imageView*/public void loadBitmap(String url, ImageView imageView) {  loadBitmap(url, imageView, this.defaultBmp, 0, 0);}/*** 加载图片-可设置加载失败后显示的默认图片* @param url* @param imageView* @param defaultBmp*/public void loadBitmap(String url, ImageView imageView, Bitmap defaultBmp) {  loadBitmap(url, imageView, defaultBmp, 0, 0);}/*** 加载图片-可指定显示图片的高宽* @param url* @param imageView* @param width* @param height*/public void loadBitmap(String url, ImageView imageView, Bitmap defaultBmp, int width, int height) {  imageViews.put(imageView, url);  Bitmap bitmap = getBitmapFromCache(url);  if (bitmap != null) {  //显示缓存图片imageView.setImageBitmap(bitmap);  } else {  //加载SD卡中的图片缓存String filename = FileUtils.getFileName(url);String filepath = imageView.getContext().getFilesDir() + File.separator + filename;File file = new File(filepath);if(file.exists()){//显示SD卡中的图片缓存Bitmap bmp = ImageUtils.getBitmap(imageView.getContext(), filename);imageView.setImageBitmap(bmp);}else{//线程加载网络图片imageView.setImageBitmap(defaultBmp);queueJob(url, imageView, width, height);}}  }  /*** 从缓存中获取图片* @param url*/public Bitmap getBitmapFromCache(String url) {  Bitmap bitmap = null;if (cache.containsKey(url)) {  bitmap = cache.get(url).get();  }  return bitmap;  }  /*** 从网络中加载图片* @param url* @param imageView* @param width* @param height*/public void queueJob(final String url, final ImageView imageView, final int width, final int height) {   final Handler handler = new Handler() {  public void handleMessage(Message msg) {  String tag = imageViews.get(imageView);  if (tag != null && tag.equals(url)) {  if (msg.obj != null) {  imageView.setImageBitmap((Bitmap) msg.obj);  try {//向SD卡中写入图片缓存ImageUtils.saveImage(imageView.getContext(), FileUtils.getFileName(url), (Bitmap) msg.obj);} catch (IOException e) {e.printStackTrace();}} }  }  };  pool.execute(new Runnable() {   public void run() {  Message message = Message.obtain();  message.obj = downloadBitmap(url, width, height);  handler.sendMessage(message);  }  });  } /*** 下载图片-可指定显示图片的高宽* @param url* @param width* @param height*/private Bitmap downloadBitmap(String url, int width, int height) {   Bitmap bitmap = null;try {//http加载图片bitmap = ApiClient.getNetBitmap(url);if(width > 0 && height > 0) {//指定显示图片的高宽bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);} //放入缓存cache.put(url, new SoftReference<Bitmap>(bitmap));} catch (Exception e) {e.printStackTrace();}return bitmap;  }
}

工具类使用 
实例化时,可以设置默认的显示图片:

BitmapManager bmpManager = new BitmapManager(BitmapFactory.decodeResource(context.getResources(), R.drawable.loading));

调用加载图片的方法:

bmpManager.loadBitmap(imageURL, imageView);

转载于:https://www.cnblogs.com/daocaowu/p/3172739.html

列表异步线程加载图片相关推荐

  1. Android:ViewPager详解(异步网络加载图片,带图片缓存,并带导航小圆点)

    android 应用中,如欢迎指引页面, 和图片轮播功能, 或者更多的内容在一页显示不了,要分成多个页面,这时候viewpager是很好用的. 首先看下效果: 下面是一个例子,带异步网络加载图片,并带 ...

  2. PhotoSwipe异步动态加载图片

    在开发搜房家居M站的时候,搜房家居装修效果图相册展示效果需要用到PhotoSwipe插件来显示图片. 特点: 1. 家居提供的接口,每次只能获取一张图片 2. 装修效果图的张数不限. 3. 从Phot ...

  3. html photoswipe原理,PhotoSwipe异步动态加载图片方法

    在开发搜房家居M站的时候,搜房家居装修效果图相册展示效果需要用到PhotoSwipe插件来显示图片. 特点:1. 家居提供的接口,每次只能获取一张图片 2. 装修效果图的张数不限. 3. 从Photo ...

  4. Android之ListView异步加载图片且仅显示可见子项中的图片

    折腾了好多天,遇到 N 多让人崩溃无语的问题,不过今天终于有些收获了,这是实验的第一版,有些混乱,下一步进行改造细分,先把代码记录在这儿吧. 网上查了很多资料,发现都千篇一律,抄来抄去,很多细节和完整 ...

  5. 演化理解 Android 异步加载图片

    引用:http://www.cnblogs.com/ghj1976/archive/2011/05/06/2038738.html 下面测试使用的layout文件: 简单来说就是 LinearLayo ...

  6. android 异步加载图片总结

    一Handler+Runnable模式 我们先看一个并不是异步线程加载的例子,使用 Handler+Runnable模式. 这里为何不是新开线程的原因请参看这篇文章:Android Runnable ...

  7. iOS开发 关于tableView加载图片时出现卡顿时的解决办法

    新手做开发的时候一般都会遇到使用tableView从网上加载图片并显示图文的时候会有卡顿现象,而这种卡顿现象也是因为多种原因造成的.一般可以分为两种:一种是由于网上加载图片需要动态定义cell的高度( ...

  8. Android实现异步从网络加载图片列表

     博文出处:http://blog.csdn.net/carterjin/article/details/7995935 有时会有在加载ListView的时候,包含用户头像或其他需要到网络获取的图 ...

  9. Android进阶:ListView性能优化异步加载图片 使滑动效果流畅

    ListView 是一种可以显示一系列项目并能进行滚动显示的 View,每一行的Item可能包含复杂的结构,可能会从网络上获取icon等的一些图标信息,就现在的网络速度要想保持ListView运行的很 ...

最新文章

  1. Leangoo大讲堂:免费Scrum敏捷开发实战—武汉站
  2. 加密_easy_crypto
  3. 大数据分析中国冬季重度雾霾的成因(二)
  4. CentOS 7文件系统与日志分析详解
  5. 自主可控的全数字实时仿真软件SkyEye支持PowerPC指令级仿真
  6. MySQL修改,表结构大幅修改
  7. make,make install命令
  8. ubuntu 安装配置mysql
  9. ROST情感分析的语法规则_《自然语言处理入门》12.依存句法分析--提取用户评论...
  10. VBA collection函数回传
  11. 设计模式(四)行为型之模板方法模式、策略模式、命令模式、责任链模式
  12. vb6.0企业版id_国网公司十八项反措(2018版)开关设备专题解读
  13. 梦飞苍穹c语言答案,梦飞仙途-楔子一  决战苍穹之巅-汤圆创作
  14. 一招教你电脑微信双开
  15. 牙疼怎么快速止痛,三招解决牙痛立竿见影
  16. rip路由协议计算机网络实验报告,RIP 动态路由协议的配置(实验报告).doc
  17. Selenium自动化测试框架—简单了解
  18. keil5安装及注册许可
  19. VS2019 .NetCore智能提示从英文变成中文设置
  20. 《第一行代码》12.2学习中遇到的一些问题and心得

热门文章

  1. 数字IC设计经典书籍
  2. java 字符串子串_java实现字符串匹配求两个字符串的最大公共子串
  3. @value注解_Java系列之注解
  4. java rsa_java中RSA加解密的实现
  5. imp oracle full,Oracle 10g imp 之 full database (转官档)
  6. 亲历2013年TED大会:全球最潮灵感大会
  7. 对url给后台传数据的时候特殊字符需要转义
  8. 分布式工具的一次小升级⏫ 1
  9. Qt与FFmpeg联合开发指南(二)——解码(2):封装和界面设计
  10. MySQL触发器 trigger学习