zoukankan      html  css  js  c++  java
  • Android进阶:ListView性能优化异步加载图片 使滑动效果流畅

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

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

    实现这样功能的类

    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()等操作

          

    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的实现

     

         

    [c-sharp] view plaincopy
    1. ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl);  
    2.                if (imageViewByTag != null) {  
    3.                    imageViewByTag.setImageDrawable(imageDrawable);  
    4.                }  

     

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

     

        

    [c-sharp] view plaincopy
    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

     

     

     

     

     

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

  • 相关阅读:
    datagrid
    IntelliJ IDEA for mac 引入js注意事项
    centos7安装并配置svn
    yum使用总结
    安装php
    类视图
    django里面添加静态变量
    Ubuntu16.04安装&创建虚拟环境
    制作dockerfile, 天眼查的镜像、并运行
    dockerfile
  • 原文地址:https://www.cnblogs.com/pricks/p/3921616.html
Copyright © 2011-2022 走看看