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. 将远程git仓库里的指定分支拉取到本地(本地不存在的分支

    将远程git仓库里的指定分支拉取到本地(本地不存在的分支) https://www.cnblogs.com/hamsterPP/p/6810831.html

  2. IntelliJ IDEA2018.1、2017.3破解教程

    (1)下载破解补丁 把下载的破解补丁放在你的idea的安装目录下的bin的目录下面(如下图所示),本文示例为G:\idea\IntelliJ IDEA 2017.3.4 破解补丁下载:http://i ...

  3. SSH框架搭建详细图文教程(转)

    这篇文章看的我醍醐灌顶的感觉,比之前本科时候学习的SSH架构 要清晰数倍  非常感觉这篇博主的文章 文章链接为:http://blog.sina.com.cn/s/blog_a6a6b3cd01017 ...

  4. grid - 网格项目跨行或跨列

    默认情况下网格项目跨度只有一个列和行,但可以跨越多个行和列. 1.可以通过设置grid-column-end和grid-column-start距离多个网络线号实现多个列跨越. <view cl ...

  5. linux修改目录为可读写

    发布到linux上遇到的问题, 上传目录没有写入权限 新建目录 mkdir /guangkuo/html/portal/images/upload 改为可读写 chmod -R a+w /guangk ...

  6. CAP Twelve Years Later: How the "Rules" Have Changed

    The CAP theorem asserts that any net­worked shared-data system can have only two of three desirable ...

  7. [剑指Offer]5.二维数组中的查找

    题目 在一个二维数组中,每一行都依照从左到右递增的顺序排序,每一列都依照从上到下递增的顺序排序.请完毕一个函数,输入这种一个二维数组和一个整数.推断数组中是否含有该整数. 思路 [算法系列之三十三]杨 ...

  8. R语言编程艺术#03#列表(list)

    向量的元素要求都是同类型的,而列表(list)与向量不同,可以组合多个不同类型的对象.类似于C语言中的结构体(struct)类型. 1.创建列表 从技术上讲,列表就是向理.之前我们接触过的普通向量都称 ...

  9. C++ 类占用空间计算方式

    1.一个类占用的空间主要是属性占用空间,而成员函数一般不占用空间,但是虚函数占用空间,需要说明的是,无论多少个虚函数,只要占用4个字节即可,也就是索引指向一个虚拟表的首位置.另外需要说明的是占用空间都 ...

  10. Git 修正错误

    大部分的人都会犯错.所以每VCS提供了一个功能,修正错误,直到特定的点. Git提供功能使用,我们可以撤销已作出的修改到本地资源库. 假设用户不小心做了一些更改,以他的本地的仓库,现在他要扔掉这些变化 ...