`
hunankeda110
  • 浏览: 747072 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

listView 图片加载性能优化

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



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



实现这样功能的类





[java] view plaincopyprint?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); 
    } 

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

       [java] view plaincopyprint?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; 
    } 
}  
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的实现



      [c-sharp] view plaincopyprint?ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl); 
               if (imageViewByTag != null) { 
                   imageViewByTag.setImageDrawable(imageDrawable); 
               } 
ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl);
                if (imageViewByTag != null) {
                    imageViewByTag.setImageDrawable(imageDrawable);
                }



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



     [c-sharp] view plaincopyprint?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; 
    } 
}  
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
分享到:
评论

相关推荐

    Listview的异步加载性能优化

    本篇文章将深入探讨ListView的异步加载性能优化,以及如何利用ViewHolder、图片缓存和异步加载策略来提升用户体验。 首先,ViewHolder模式是ListView性能优化的基础。这个模式的主要目的是减少对视图的查找和更新...

    ListView性能优化之视图缓存

    ListView 的性能优化可以从多方面入手,包括 Adapter 的优化、视图缓存、数据加载优化等。其中,Adapter 的优化是 ListView 性能优化的关键所在。Google I/O 大会提供了多种优化 Adapter 的方案,包括使用 ...

    listview加载多幅图片

    总之,ListView加载多幅图片涉及到ImageList的使用,图片的加载和存储策略,以及性能优化。通过合理的编程实践,可以创建出流畅且高效的图片展示效果。同时,理解并掌握这些知识点对于开发高质量的UI界面至关重要。

    ListView异步加载图片

    在实际项目中,还应考虑优化ListView的滚动性能,如使用ViewHolder模式减少视图查找的开销,以及根据ListView的可见区域动态加载或取消加载图片,避免一次性加载过多图片导致内存压力过大。这些技巧与异步加载图片...

    关于listview item重用导致图片重复加载 图片重新请求

    以下是如何使用这个库来优化图片加载的步骤: 1. **集成库**:首先,需要在项目中引入Android-Universal-Image-Loader库。可以通过Gradle依赖或者直接下载库文件添加到项目中。 2. **配置ImageLoader**:初始化...

    Android开发之listview优化+图片异步加载缓存+避免图片显示闪烁

    综上所述,通过ListView的优化、图片的异步加载和缓存策略,以及避免图片闪烁的方法,可以显著提升Android应用的性能和用户体验。实际开发中,结合具体情况灵活运用这些技术,能有效地解决类似问题。

    listview 异步加载网络图片

    10. **总结**:在Android的ListView中实现异步加载网络图片,需要结合异步处理框架、选择合适的图片库、优化缓存策略、合理管理内存,并对ListView进行优化。通过这些手段,可以显著提升应用的性能和用户体验。

    listview的图像加载

    针对这些问题,我们可以采用缓存机制和第三方库如xutil来优化图片加载,提升用户体验。 首先,我们要理解ListView的复用机制。当ListView滚动时,为了提高性能,已经滑出屏幕的item会被重新利用来显示新的内容。...

    ListView 延迟加载图片 改进

    标题“ListView延迟加载图片改进”正是针对这个问题,通过延迟加载技术来提升用户体验。 延迟加载(Lazy Loading)是一种策略,它不一次性加载所有图片,而是当用户滚动到某一个列表项时,才加载对应的图片。这种...

    ListView异步加载网络图片

    因此,"ListView异步加载网络图片"是一个重要的优化技巧。 异步加载的基本思路是将图片下载和显示的操作放在后台线程进行,避免占用主线程资源,确保UI的流畅。在Android中,可以使用多种方式实现这一目标,例如...

    android listView 异步加载图片

    总的来说,“android listView 异步加载图片”是一个重要的性能优化技巧,它涉及到多线程编程、内存管理、图片处理等多个Android开发的核心知识点。正确实现这一功能,可以显著提升用户体验,使应用程序更加流畅。

    listview 分页加载,优化

    ListView是Android平台上常见的一种用于展示大量数据的视图组件,尤其在处理长列表时,它的分页加载和优化显得尤为重要。以下将详细讲解ListView的分页加载机制以及相关的优化策略。 1. **分页加载原理**: 分页...

    ListView异步加载图片进度条

    在处理大量图片时,为了提升用户体验和优化性能,通常会采用异步加载图片的技术。本文将深入探讨如何实现ListView中图片的异步加载,并结合进度条显示加载状态,使代码更加规范。 一、异步加载图片的重要性 在...

    Android Listview异步加载图片

    综上所述,Android ListView中异步加载图片是优化用户体验的关键。通过选择合适的异步加载策略和处理图片错位问题,我们可以确保ListView流畅运行,提供优质的用户体验。同时,利用第三方库可以大大简化代码,提高...

    android listView图片异步加载(拖动时不加载,双缓存)

    因此,我们需要采用异步加载图片的方式,同时为了优化性能,通常会采用双缓存策略。本文将详细介绍如何在ListView中实现图片的异步加载,并且在用户拖动时不加载,以提高滚动流畅性。 一、异步加载原理 异步加载是...

    listview 只加载当前屏幕内项目

    在Android开发中,ListView是一种常见...总的来说,这个话题涉及到ListView的性能优化、内存管理以及异步任务的使用,这些都是Android开发中的核心知识点。理解和掌握这些技术能够帮助开发者创建更加流畅、高效的应用。

    listview异步加载图片

    为了解决这个问题,我们需要实现图片的异步加载,并且通常会结合三级缓存机制来优化性能。本文将详细讲解如何在ListView中实现异步加载图片以及三级缓存的原理。 ### 一、异步加载图片的必要性 1. **避免阻塞主线...

    listview高级部分,性能优化的demo

    本示例“ListView高级部分,性能优化的demo”将深入探讨六个关键领域的优化策略,帮助开发者提升ListView的运行效率,提供更好的用户体验。 1. **ViewHolder模式**:这是ListView性能优化的核心。通过复用已创建的...

    android listview 加载图片错乱(错位)

    然而,开发者在实现ListView加载图片时可能会遇到图片错乱或错位的问题,这通常是由于不当的图片加载策略或者ListView的复用机制导致的。本篇文章将深入探讨这个问题,并提供解决方案。 一、ListView图片错乱的原因...

Global site tag (gtag.js) - Google Analytics