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

所以这里就需要把这些信息利用多线程实现异步加载

实现这样功能的类

  1. public class AsyncImageLoader {
  2. private HashMap<String, SoftReference<Drawable>> imageCache;
  3. public AsyncImageLoader() {
  4. imageCache = new HashMap<String, SoftReference<Drawable>>();
  5. }
  6. public Drawable loadDrawable(final String imageUrl, final ImageCallback imageCallback) {
  7. if (imageCache.containsKey(imageUrl)) {
  8. SoftReference<Drawable> softReference = imageCache.get(imageUrl);
  9. Drawable drawable = softReference.get();
  10. if (drawable != null) {
  11. return drawable;
  12. }
  13. }
  14. final Handler handler = new Handler() {
  15. @Override
  16. public void handleMessage(Message message) {
  17. imageCallback.imageLoaded((Drawable) message.obj, imageUrl);
  18. }
  19. };
  20. new Thread() {
  21. @Override
  22. public void run() {
  23. Drawable drawable = loadImageFromUrl(imageUrl);
  24. imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
  25. Message message = handler.obtainMessage(0, drawable);
  26. handler.sendMessage(message);
  27. }
  28. }.start();
  29. return null;
  30. }
  31. public static Drawable loadImageFromUrl(String url) {
  32. // ...
  33. }
  34. public interface ImageCallback {
  35. public void imageLoaded(Drawable imageDrawable, String imageUrl);
  36. }
  37. }

注意这里使用了 SoftReference来缓存图片,允许 GC在需要的时候可以对缓存中的图片进行清理。它这样工作:

·         调用 loadDrawable(ImageUrl, imageCallback),传入一个匿名实现的 ImageCallback接口

·         如果图片在缓存中不存在的话,图片将从单一的线程中下载并在下载结束时通过 ImageCallback回调

·         如果图片确实存在于缓存中,就会马上返回,不会回调 ImageCallback

然后我们还可以根据09google I/0开发者大会提到的方式来继续优化Adapter 使用ViewHolder来减少一些比较费时的操作,譬如inflate XML 和 findViewById()等操作

  1. public class ImageAndTextListAdapter extends ArrayAdapter<ImageAndText> {
  2. private ListView listView;
  3. private AsyncImageLoader asyncImageLoader;
  4. public ImageAndTextListAdapter(Activity activity, List<ImageAndText> imageAndTexts, ListView listView) {
  5. super(activity, 0, imageAndTexts);
  6. this.listView = listView;
  7. asyncImageLoader = new AsyncImageLoader();
  8. }
  9. @Override
  10. public View getView(int position, View convertView, ViewGroup parent) {
  11. Activity activity = (Activity) getContext();
  12. // Inflate the views from XML
  13. View rowView = convertView;
  14. ViewCache viewCache;
  15. if (rowView == null) {
  16. LayoutInflater inflater = activity.getLayoutInflater();
  17. rowView = inflater.inflate(R.layout.image_and_text_row, null);
  18. viewCache = new ViewCache(rowView);
  19. rowView.setTag(viewCache);
  20. } else {
  21. viewCache = (ViewCache) rowView.getTag();
  22. }
  23. ImageAndText imageAndText = getItem(position);
  24. // Load the image and set it on the ImageView
  25. String imageUrl = imageAndText.getImageUrl();
  26. ImageView imageView = viewCache.getImageView();
  27. imageView.setTag(imageUrl);
  28. Drawable cachedImage = asyncImageLoader.loadDrawable(imageUrl, new ImageCallback() {
  29. public void imageLoaded(Drawable imageDrawable, String imageUrl) {
  30. ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl);
  31. if (imageViewByTag != null) {
  32. imageViewByTag.setImageDrawable(imageDrawable);
  33. }
  34. }
  35. });
  36. imageView.setImageDrawable(cachedImage);
  37. // Set the text on the TextView
  38. TextView textView = viewCache.getTextView();
  39. textView.setText(imageAndText.getText());
  40. return rowView;
  41. }
  42. }

这里我们没有加载完iamge之后直接设定到相应的ImageView上 ,而是通过Tag查找,这里我们重用的View 这里有个listView的引用来通过Tag查找 可见 CallBack的实现

  1. ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl);
  2. if (imageViewByTag != null) {
  3. imageViewByTag.setImageDrawable(imageDrawable);
  4. }

这里通过ViewCatch来减少了 findViewById的使用

  1. public class ViewCache {
  2. private View baseView;
  3. private TextView textView;
  4. private ImageView imageView;
  5. public ViewCache(View baseView) {
  6. this.baseView = baseView;
  7. }
  8. public TextView getTextView() {
  9. if (textView == null) {
  10. textView = (TextView) baseView.findViewById(R.id.text);
  11. }
  12. return titleView;
  13. }
  14. public ImageView getImageView() {
  15. if (imageView == null) {
  16. imageView = (ImageView) baseView.findViewById(R.id.image);
  17. }
  18. return imageView;
  19. }
  20. }

总结 :这里主要做了三点优化

  • 在单一线程里加载图片
  • 重用列表中行
  • 缓存行中的 View

转自:http://blog.csdn.net/wanglong0537/article/details/6334005

Android进阶:ListView性能优化异步加载图片 使滑动效果流畅的更多相关文章

  1. 【Android】ListView、RecyclerView异步加载图片引起错位问题

    今天在RecyclerView列表里遇到一个情况,它包含300条数据,每项包含一个图片,发现在首次载入时,由于本地没图,请求网络的时候:快速滑动导致了图片错位.闪烁的问题. 原理的话有一篇已经说的很清 ...

  2. ListView与GridView异步加载图片

    原理很简单,主要是用到了回调方法,下面是异步加载图片的类 <span style="font-size:16px;">package com.xxx.xxx; impo ...

  3. 又优化了一下 Android ListView 异步加载图片

    写这篇文章并不是教大家怎么样用listview异步加载图片,因为这样的文章在网上已经有很多了,比如这位仁兄写的就很好: http://www.iteye.com/topic/685986 我也是因为看 ...

  4. Android中ListView异步加载图片错位、重复、闪烁问题分析及解决方案

    我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图片错位.重复.闪烁等问题,其实这些问题总结起来就是一个问题,我们需要对这些问题进行ListView的优化. 比如L ...

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

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

  6. Android的ListView异步加载图片时,错位、重复、闪烁问题的分析及解决方法

    Android ListView异步加载图片错位.重复.闪烁分析以及解决方案,具体问题分析以及解决方案请看下文. 我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图 ...

  7. Listview 异步加载图片之优化篇(有图有码有解释)

    在APP应用中,listview的异步加载图片方式能够带来很好的用户体验,同时也是考量程序性能的一个重要指标.关于listview的异步加载,网上其实很多示例了,中心思想都差不多,不过很多版本或是有b ...

  8. android Listview 软引用SoftReference异步加载图片

    首先说一下,android系统加载大量图片系统内存溢出的3中解决方法: (1)从网络或本地加载图片的时候,只加载缩略图.这个方法的确能够少占用不少内存,可是它的致命的缺点就是,因为加载的是缩略图,所以 ...

  9. Listview异步加载图片之优化篇

    在APP应用中,listview的异步加载图片方式能够带来很好的用户体验,同时也是考量程序性能的一个重要指标.关于listview的异步加载,网上其实很多示例了,中心思想都差不多,不过很多版本或是有b ...

随机推荐

  1. Spark MLlib 之 StringIndexer、IndexToString使用说明以及源码剖析

    最近在用Spark MLlib进行特征处理时,对于StringIndexer和IndexToString遇到了点问题,查阅官方文档也没有解决疑惑.无奈之下翻看源码才明白其中一二...这就给大家娓娓道来 ...

  2. tensorflow之数据读取探究(2)

    tensorflow之tfrecord数据读取 Tensorflow关于TFRecord格式文件的处理.模型的训练的架构为: 1.获取文件列表.创建文件队列:http://blog.csdn.net/ ...

  3. jQuery应用一之验证插件validate的使用

    综述 validate是一个用来验证表单提交的插件,应用十分广泛,具有如下的几个功能 自带了基本的验证规则 提供了丰富的验证信息提示功能 多种事件触发验证 自定义验证规则 下面我们就来感受一下这个插件 ...

  4. 添加JavaDoc

    使用javadoc比较容易生成文档,命令如下: javadoc -d doc -sourcepath src/main/java/ -subpackages com -encoding UTF-8 - ...

  5. PL/SQL学习笔记之条件控制语句

    一:IF-THEN语句 IF (condition) THEN commands; END IF; 二:IF-THEN_ELSE语句 IF (condition) THEN S1; ELSE S2; ...

  6. JProfiler进行Java运行时内存分析

    原文地址:https://www.cnblogs.com/onmyway20xx/p/3963735.html 在最近的工作中,通过JProfiler解决了一个内存泄漏的问题,现将检测的步骤和一些分析 ...

  7. PHP——自定义比较算法

    很多时候,程序都是直接写好逻辑运算,提供给用户的是一个值,然后后台去比较:但是有时会提供一种类似计算器一样的交互方式的时候,PHP只能读懂用户的输入来进行比较了- 最近的一个项目涉及到一个由用户自定义 ...

  8. SNF快速开发平台MVC-表格单元格合并组件

    1.   表格单元格合并组件 1.1.      效果展示 1.1.1.    页面展现表格合并单元格 图 4.1 1.1.2.    导出excel合并单元格 图 4.2 1.2.      调用说 ...

  9. 基于mindwave脑电波进行疲劳检测算法的设计(1)

    一.简介 脑波,又称之为脑电波,是人大脑发出的电波,非常的微弱,只能通过设备来检测.人的脑波在不同状态下,会不同,因此可以通过脑波来量化分析人的精神状态. 科学家讲脑电波分为四种,以下为详细解释 (1 ...

  10. python requests库使用

    迫不及待了吗?本页内容为如何入门 Requests 提供了很好的指引.其假设你已经安装了 Requests.如果还没有,去安装一节看看吧. 首先,确认一下: Requests 已安装 Requests ...