Android实现ListView异步加载图片的方法

时间:2022-01-05 06:27:50

本文实例讲述了Android实现ListView异步加载图片的方法。分享给大家供大家参考。具体如下:

ListView异步加载图片是非常实用的方法,凡是是要通过网络获取图片资源一般使用这种方法比较好,用户体验好,不用让用户等待下去,下面就说实现方法,先贴上主方法的代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package cn.wangmeng.test;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
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() {
   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) {
  URL m;
  InputStream i = null;
  try {
  m = new URL(url);
  i = (InputStream) m.getContent();
  } catch (MalformedURLException e1) {
  e1.printStackTrace();
  } catch (IOException e) {
  e.printStackTrace();
  }
  Drawable d = Drawable.createFromStream(i, "src");
  return d;
 }
 public interface ImageCallback {
  public void imageLoaded(Drawable imageDrawable, String imageUrl);
  }
}

以上代码是实现异步获取图片的主方法,SoftReference是软引用,是为了更好的为了系统回收变量,重复的URL直接返回已有的资源,实现回调函数,让数据成功后,更新到UI线程。

几个辅助类文件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package cn.wangmeng.test;
public class ImageAndText {
 private String imageUrl;
 private String text;
 public ImageAndText(String imageUrl, String text) {
  this.imageUrl = imageUrl;
  this.text = text;
 }
 public String getImageUrl() {
  return imageUrl;
 }
 public String getText() {
  return text;
 }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package cn.wangmeng.test;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
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 textView;
 }
 public ImageView getImageView() {
  if (imageView == null) {
  imageView = (ImageView) baseView.findViewById(R.id.image);
  }
  return imageView;
 }
}

ViewCache是辅助获取adapter的子元素布局:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package cn.wangmeng.test;
import java.util.List;
import cn.wangmeng.test.AsyncImageLoader.ImageCallback;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
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();
 }
 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);
   }
  }
  });
  if (cachedImage == null) {
  imageView.setImageResource(R.drawable.default_image);
  }else{
  imageView.setImageDrawable(cachedImage);
  }
  // Set the text on the TextView
  TextView textView = viewCache.getTextView();
  textView.setText(imageAndText.getText());
  return rowView;
 }
}

ImageAndTextListAdapter是实现ListView的Adapter,里面有个技巧就是imageView.setTag(imageUrl),setTag是存储数据的,这样是为了保证在回调函数时,listview去更新自己对应item,大家仔细阅读就知道了。

最后贴出布局文件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content">
 <ImageView android:id="@+id/image"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   />
 <TextView android:id="@+id/text"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>
</LinearLayout>

运行效果截图如下:

Android实现ListView异步加载图片的方法

希望本文所述对大家的C#程序设计有所帮助。