list 异步加载图片

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

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

实现这样功能的类

  1. publicclassAsyncImageLoader{
  2. privateHashMap<String,SoftReference<Drawable>>imageCache;
  3. publicAsyncImageLoader(){
  4. imageCache=newHashMap<String,SoftReference<Drawable>>();
  5. }
  6. publicDrawableloadDrawable(finalStringimageUrl,finalImageCallbackimageCallback){
  7. if(imageCache.containsKey(imageUrl)){
  8. SoftReference<Drawable>softReference=imageCache.get(imageUrl);
  9. Drawabledrawable=softReference.get();
  10. if(drawable!=null){
  11. returndrawable;
  12. }
  13. }
  14. finalHandlerhandler=newHandler(){
  15. @Override
  16. publicvoidhandleMessage(Messagemessage){
  17. imageCallback.imageLoaded((Drawable)message.obj,imageUrl);
  18. }
  19. };
  20. newThread(){
  21. @Override
  22. publicvoidrun(){
  23. Drawabledrawable=loadImageFromUrl(imageUrl);
  24. imageCache.put(imageUrl,newSoftReference<Drawable>(drawable));
  25. Messagemessage=handler.obtainMessage(0,drawable);
  26. handler.sendMessage(message);
  27. }
  28. }.start();
  29. returnnull;
  30. }
  31. publicstaticDrawableloadImageFromUrl(Stringurl){
  32. //...
  33. }
  34. publicinterfaceImageCallback{
  35. publicvoidimageLoaded(DrawableimageDrawable,StringimageUrl);
  36. }
  37. }

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

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

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

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

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

  1. publicclassImageAndTextListAdapterextendsArrayAdapter<ImageAndText>{
  2. privateListViewlistView;
  3. privateAsyncImageLoaderasyncImageLoader;
  4. publicImageAndTextListAdapter(Activityactivity,List<ImageAndText>imageAndTexts,ListViewlistView){
  5. super(activity,0,imageAndTexts);
  6. this.listView=listView;
  7. asyncImageLoader=newAsyncImageLoader();
  8. }
  9. @Override
  10. publicViewgetView(intposition,ViewconvertView,ViewGroupparent){
  11. Activityactivity=(Activity)getContext();
  12. //InflatetheviewsfromXML
  13. ViewrowView=convertView;
  14. ViewCacheviewCache;
  15. if(rowView==null){
  16. LayoutInflaterinflater=activity.getLayoutInflater();
  17. rowView=inflater.inflate(R.layout.image_and_text_row,null);
  18. viewCache=newViewCache(rowView);
  19. rowView.setTag(viewCache);
  20. }else{
  21. viewCache=(ViewCache)rowView.getTag();
  22. }
  23. ImageAndTextimageAndText=getItem(position);
  24. //LoadtheimageandsetitontheImageView
  25. StringimageUrl=imageAndText.getImageUrl();
  26. ImageViewimageView=viewCache.getImageView();
  27. imageView.setTag(imageUrl);
  28. DrawablecachedImage=asyncImageLoader.loadDrawable(imageUrl,newImageCallback(){
  29. publicvoidimageLoaded(DrawableimageDrawable,StringimageUrl){
  30. ImageViewimageViewByTag=(ImageView)listView.findViewWithTag(imageUrl);
  31. if(imageViewByTag!=null){
  32. imageViewByTag.setImageDrawable(imageDrawable);
  33. }
  34. }
  35. });
  36. imageView.setImageDrawable(cachedImage);
  37. //SetthetextontheTextView
  38. TextViewtextView=viewCache.getTextView();
  39. textView.setText(imageAndText.getText());
  40. returnrowView;
  41. }
  42. }

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

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

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

  1. publicclassViewCache{
  2. privateViewbaseView;
  3. privateTextViewtextView;
  4. privateImageViewimageView;
  5. publicViewCache(ViewbaseView){
  6. this.baseView=baseView;
  7. }
  8. publicTextViewgetTextView(){
  9. if(textView==null){
  10. textView=(TextView)baseView.findViewById(R.id.text);
  11. }
  12. returntitleView;
  13. }
  14. publicImageViewgetImageView(){
  15. if(imageView==null){
  16. imageView=(ImageView)baseView.findViewById(R.id.image);
  17. }
  18. returnimageView;
  19. }
  20. }

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值