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. ie6定位absolute bug触发layout解决

    IE6中很多Bug都可以通过触发layout得到解决,以上的解决方法无论是设置zoom:1还是设置width和height其实都是为了触发layout.下列的CSS属性或取值会让一个元素获得layou ...

  2. .net core 3.0中可以使用gRPC了

    今天发现.net core下有gRPC模板了,这个可是补全了.net core下高性能RPC框架缺失这一大短板了. 使用模板创建了工程后,发现连客户端的示例也创建了. 更加给力的是,IDE是能直接识别 ...

  3. Knockout.Js官网学习(Mapping高级用法一)

    前言 有时候,在使用ko.mapping.fromJS的时候,可能有必要去使用mapping的高级用法来定义mapping的详细过程,以后定义了,以后再调用的时候就不必再定义了.这里有一些情形,你可能 ...

  4. [Android Pro] Android P版本 新功能介绍和兼容性处理(三)Android Studio 3.0 ~ 3.2 其他特性

    cp : https://blog.csdn.net/yi_master/article/details/80067198 1:JAVA8特性支持 1)Base64.java 在升级到as3.0之后, ...

  5. 递归与迭代的联系以及优缺点(以c++为例)

    1.递归的定义: 程序直接或间接的调用自身的方法. 递归算法的特点:(1) 递归就是在过程或函数里调用自身.(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口.(3) 递归算法解题通 ...

  6. Verilog 加法器和减法器(8)-串行加法器

    如果对速度要求不高,我们也可以使用串行加法器.下面通过状态机来实现串行加法器的功能. 设A=an-1an-2-a0, B=bn-1bn-2-b0,是要相加的两个无符号数,相加的和为:sum=sn-1s ...

  7. Kafka与常见消息队列的对比

    Kafka与常见消息队列的对比 RabbitMQ Erlang编写 支持很多的协议:AMQP,XMPP, SMTP, STOMP 非常重量级,更适合于企业级的开发 发送给客户端时先在中心队列排队.对路 ...

  8. js 创建Date对象5种方式

    new Date("month dd,yyyy hh:mm:ss"); new Date("month dd,yyyy"); new Date(yyyy,mth ...

  9. 【T07】不要低估tcp的性能

    1.tcp在ip的基础上增加了校验和.可靠性和流量控制的功能,而udp只增加了校验和的功能,看起来udp应该会比tcp快很多, 但事实不是这样,有时候tcp比udp的性能还要好. 2.思考,在什么情况 ...

  10. 摄像专用的SD卡推荐

      此类SD卡主要需要满足快速写入:特别对于4K的支持,速度要有很高才能满足. 文章来源:刘俊涛的博客 欢迎关注,有问题一起学习欢迎留言.评论