zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    AtCoder Beginner Contest 167
    AtCoder Beginner Contest 166
    AtCoder Beginner Contest 165
    AtCoder Beginner Contest 164
    AtCoder Beginner Contest 163
    AtCoder Beginner Contest 162
    AtCoder Beginner Contest 161
    AtCoder Beginner Contest 160
    AtCoder Beginner Contest 159
    自定义Mybatis自动生成代码规则
  • 原文地址:https://www.cnblogs.com/moonvan/p/2024957.html
Copyright © 2011-2022 走看看