MyException - 我的异常网
当前位置:我的异常网» Android » Android进阶:ListView性能优化异步加载图片 使滑动

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

www.MyException.Cn  网友分享于:2013-06-29  浏览:215次
Android进阶:ListView性能优化异步加载图片 使滑动效果流畅

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

 

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

 

实现这样功能的类

 

 

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

 

 

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

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

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

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

 

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

      

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

 

 

 

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

 

     

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

 

 

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

 

    

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

 

 

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

 

 

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

文章评论

科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
为什么程序员都是夜猫子
为什么程序员都是夜猫子
中美印日四国程序员比较
中美印日四国程序员比较
每天工作4小时的程序员
每天工作4小时的程序员
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
总结2014中国互联网十大段子
总结2014中国互联网十大段子
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
程序员和编码员之间的区别
程序员和编码员之间的区别
Java程序员必看电影
Java程序员必看电影
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
旅行,写作,编程
旅行,写作,编程
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
鲜为人知的编程真相
鲜为人知的编程真相
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
编程语言是女人
编程语言是女人
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
程序员应该关注的一些事儿
程序员应该关注的一些事儿
漫画:程序员的工作
漫画:程序员的工作
 程序员的样子
程序员的样子
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
老程序员的下场
老程序员的下场
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
如何成为一名黑客
如何成为一名黑客
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
10个调试和排错的小建议
10个调试和排错的小建议
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
我是如何打败拖延症的
我是如何打败拖延症的
一个程序员的时间管理
一个程序员的时间管理
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
我的丈夫是个程序员
我的丈夫是个程序员
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
程序员的鄙视链
程序员的鄙视链
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有