• list多线程实现异步加载


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

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

    实现这样功能的类

    view plaincopy to clipboardprint?
    01.public class AsyncImageLoader {  
    02.    private HashMap<String, SoftReference<Drawable>> imageCache;  
    03.   
    04.    public AsyncImageLoader() {  
    05.        imageCache = new HashMap<String, SoftReference<Drawable>>();  
    06.    }  
    07.   
    08.    public Drawable loadDrawable(final String imageUrl, final ImageCallback imageCallback) {  
    09.        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.} 
    public class AsyncImageLoader {
        private HashMap<String, SoftReference<Drawable>> imageCache;
     
        public AsyncImageLoader() {
            imageCache = new HashMap<String, SoftReference<Drawable>>();
        }
     
        public Drawable loadDrawable(final String imageUrl, final ImageCallback imageCallback) {
            if (imageCache.containsKey(imageUrl)) {
                SoftReference<Drawable> softReference = imageCache.get(imageUrl);
                Drawable drawable = softReference.get();
                if (drawable != null) {
                    return drawable;
                }
            }
            final Handler handler = new Handler() {
                @Override
                public void handleMessage(Message message) {
                    imageCallback.imageLoaded((Drawable) message.obj, imageUrl);
                }
            };
            new Thread() {
                @Override
                public void run() {
                    Drawable drawable = loadImageFromUrl(imageUrl);
                    imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
                    Message message = handler.obtainMessage(0, drawable);
                    handler.sendMessage(message);
                }
            }.start();
            return null;
        }
     
        public static Drawable loadImageFromUrl(String url) {
            // ...
        }
     
        public interface ImageCallback {
            public void imageLoaded(Drawable imageDrawable, String imageUrl);
        }
    }
     

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

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

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

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

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

          
    view plaincopy to clipboardprint?
    01.public class ImageAndTextListAdapter extends ArrayAdapter<ImageAndText> {  
    02.   
    03.    private ListView listView;  
    04.    private AsyncImageLoader asyncImageLoader;  
    05.   
    06.    public ImageAndTextListAdapter(Activity activity, List<ImageAndText> imageAndTexts, ListView listView) {  
    07.        super(activity, 0, imageAndTexts);  
    08.        this.listView = listView;  
    09.        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.}  
    public class ImageAndTextListAdapter extends ArrayAdapter<ImageAndText> {
     
        private ListView listView;
        private AsyncImageLoader asyncImageLoader;
     
        public ImageAndTextListAdapter(Activity activity, List<ImageAndText> imageAndTexts, ListView listView) {
            super(activity, 0, imageAndTexts);
            this.listView = listView;
            asyncImageLoader = new AsyncImageLoader();
        }
     
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            Activity activity = (Activity) getContext();
     
            // Inflate the views from XML
            View rowView = convertView;
            ViewCache viewCache;
            if (rowView == null) {
                LayoutInflater inflater = activity.getLayoutInflater();
                rowView = inflater.inflate(R.layout.image_and_text_row, null);
                viewCache = new ViewCache(rowView);
                rowView.setTag(viewCache);
            } else {
                viewCache = (ViewCache) rowView.getTag();
            }
            ImageAndText imageAndText = getItem(position);
     
            // Load the image and set it on the ImageView
            String imageUrl = imageAndText.getImageUrl();
            ImageView imageView = viewCache.getImageView();
            imageView.setTag(imageUrl);
            Drawable cachedImage = asyncImageLoader.loadDrawable(imageUrl, new ImageCallback() {
                public void imageLoaded(Drawable imageDrawable, String imageUrl) {
                    ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl);
                    if (imageViewByTag != null) {
                        imageViewByTag.setImageDrawable(imageDrawable);
                    }
                }
            });
            imageView.setImageDrawable(cachedImage);
     
            // Set the text on the TextView
            TextView textView = viewCache.getTextView();
            textView.setText(imageAndText.getText());
     
            return rowView;
        }

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

         
    view plaincopy to clipboardprint?
    01.ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl);  
    02.               if (imageViewByTag != null) {  
    03.                   imageViewByTag.setImageDrawable(imageDrawable);  
    04.               } 
     ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl);
                    if (imageViewByTag != null) {
                        imageViewByTag.setImageDrawable(imageDrawable);
                    }

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

        
    view plaincopy to clipboardprint?
    01.public class ViewCache {  
    02.   
    03.    private View baseView;  
    04.    private TextView textView;  
    05.    private ImageView imageView;  
    06.   
    07.    public ViewCache(View baseView) {  
    08.        this.baseView = baseView;  
    09.    }  
    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.}  
    public class ViewCache {
     
        private View baseView;
        private TextView textView;
        private ImageView imageView;
     
        public ViewCache(View baseView) {
            this.baseView = baseView;
        }
     
        public TextView getTextView() {
            if (textView == null) {
                textView = (TextView) baseView.findViewById(R.id.text);
            }
            return titleView;
        }
     
        public ImageView getImageView() {
            if (imageView == null) {
                imageView = (ImageView) baseView.findViewById(R.id.image);
            }
            return imageView;
        }

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

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


    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wanglong0537/archive/2011/04/19/6334005.aspx

  • 相关阅读:
    RPC、HTTP、IDL
    秋招拿了7个offer,分享一些反思和经验
    “功能测试”到“测试开发”升级之路
    Github最全买房租房攻略,火了!
    王垠:怎样尊重一个程序员?
    为什么曾经优秀的人突然变得平庸?
    你这么努力,为什么能力提升还这么慢?
    打工人到什么状态,就可以离职了?
    怎样才能迅速晋升?
    如何做个优秀的经理?
  • 原文地址:https://www.cnblogs.com/moonvan/p/2024957.html
Copyright © 2020-2023  润新知