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的异步加载性能优化,以及如何利用ViewHolder、图片缓存和异步加载策略来提升用户体验。 首先,ViewHolder模式是ListView性能优化的基础。这个模式的主要目的是减少对视图的查找和更新...
ListView 的性能优化可以从多方面入手,包括 Adapter 的优化、视图缓存、数据加载优化等。其中,Adapter 的优化是 ListView 性能优化的关键所在。Google I/O 大会提供了多种优化 Adapter 的方案,包括使用 ...
总之,ListView加载多幅图片涉及到ImageList的使用,图片的加载和存储策略,以及性能优化。通过合理的编程实践,可以创建出流畅且高效的图片展示效果。同时,理解并掌握这些知识点对于开发高质量的UI界面至关重要。
在实际项目中,还应考虑优化ListView的滚动性能,如使用ViewHolder模式减少视图查找的开销,以及根据ListView的可见区域动态加载或取消加载图片,避免一次性加载过多图片导致内存压力过大。这些技巧与异步加载图片...
以下是如何使用这个库来优化图片加载的步骤: 1. **集成库**:首先,需要在项目中引入Android-Universal-Image-Loader库。可以通过Gradle依赖或者直接下载库文件添加到项目中。 2. **配置ImageLoader**:初始化...
综上所述,通过ListView的优化、图片的异步加载和缓存策略,以及避免图片闪烁的方法,可以显著提升Android应用的性能和用户体验。实际开发中,结合具体情况灵活运用这些技术,能有效地解决类似问题。
10. **总结**:在Android的ListView中实现异步加载网络图片,需要结合异步处理框架、选择合适的图片库、优化缓存策略、合理管理内存,并对ListView进行优化。通过这些手段,可以显著提升应用的性能和用户体验。
针对这些问题,我们可以采用缓存机制和第三方库如xutil来优化图片加载,提升用户体验。 首先,我们要理解ListView的复用机制。当ListView滚动时,为了提高性能,已经滑出屏幕的item会被重新利用来显示新的内容。...
标题“ListView延迟加载图片改进”正是针对这个问题,通过延迟加载技术来提升用户体验。 延迟加载(Lazy Loading)是一种策略,它不一次性加载所有图片,而是当用户滚动到某一个列表项时,才加载对应的图片。这种...
因此,"ListView异步加载网络图片"是一个重要的优化技巧。 异步加载的基本思路是将图片下载和显示的操作放在后台线程进行,避免占用主线程资源,确保UI的流畅。在Android中,可以使用多种方式实现这一目标,例如...
总的来说,“android listView 异步加载图片”是一个重要的性能优化技巧,它涉及到多线程编程、内存管理、图片处理等多个Android开发的核心知识点。正确实现这一功能,可以显著提升用户体验,使应用程序更加流畅。
ListView是Android平台上常见的一种用于展示大量数据的视图组件,尤其在处理长列表时,它的分页加载和优化显得尤为重要。以下将详细讲解ListView的分页加载机制以及相关的优化策略。 1. **分页加载原理**: 分页...
在处理大量图片时,为了提升用户体验和优化性能,通常会采用异步加载图片的技术。本文将深入探讨如何实现ListView中图片的异步加载,并结合进度条显示加载状态,使代码更加规范。 一、异步加载图片的重要性 在...
综上所述,Android ListView中异步加载图片是优化用户体验的关键。通过选择合适的异步加载策略和处理图片错位问题,我们可以确保ListView流畅运行,提供优质的用户体验。同时,利用第三方库可以大大简化代码,提高...
因此,我们需要采用异步加载图片的方式,同时为了优化性能,通常会采用双缓存策略。本文将详细介绍如何在ListView中实现图片的异步加载,并且在用户拖动时不加载,以提高滚动流畅性。 一、异步加载原理 异步加载是...
在Android开发中,ListView是一种常见...总的来说,这个话题涉及到ListView的性能优化、内存管理以及异步任务的使用,这些都是Android开发中的核心知识点。理解和掌握这些技术能够帮助开发者创建更加流畅、高效的应用。
为了解决这个问题,我们需要实现图片的异步加载,并且通常会结合三级缓存机制来优化性能。本文将详细讲解如何在ListView中实现异步加载图片以及三级缓存的原理。 ### 一、异步加载图片的必要性 1. **避免阻塞主线...
本示例“ListView高级部分,性能优化的demo”将深入探讨六个关键领域的优化策略,帮助开发者提升ListView的运行效率,提供更好的用户体验。 1. **ViewHolder模式**:这是ListView性能优化的核心。通过复用已创建的...
然而,开发者在实现ListView加载图片时可能会遇到图片错乱或错位的问题,这通常是由于不当的图片加载策略或者ListView的复用机制导致的。本篇文章将深入探讨这个问题,并提供解决方案。 一、ListView图片错乱的原因...