2014年1月18日星期六

Android实现ListView异步加载图片

Android实现ListView异步加载图片
http://www.apkbus.com/android-47-1-1.html

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

  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.lang.ref.SoftReference;
  5. import java.net.MalformedURLException;
  6. import java.net.URL;
  7. import java.util.HashMap;

  8. import android.graphics.drawable.Drawable;
  9. import android.os.Handler;
  10. import android.os.Message;

  11. public class AsyncImageLoader {

  12.          private HashMap<String, SoftReference<Drawable>> imageCache;
  13.           
  14.              public AsyncImageLoader() {
  15.                      imageCache = new HashMap<String, SoftReference<Drawable>>();
  16.              }
  17.           
  18.              public Drawable loadDrawable(final String imageUrl, final ImageCallback imageCallback) {
  19.                  if (imageCache.containsKey(imageUrl)) {
  20.                      SoftReference<Drawable> softReference = imageCache.get(imageUrl);
  21.                      Drawable drawable = softReference.get();
  22.                      if (drawable != null) {
  23.                          return drawable;
  24.                      }
  25.                  }
  26.                  final Handler handler = new Handler() {
  27.                      public void handleMessage(Message message) {
  28.                          imageCallback.imageLoaded((Drawable) message.obj, imageUrl);
  29.                      }
  30.                  };
  31.                  new Thread() {
  32.                      @Override
  33.                      public void run() {
  34.                          Drawable drawable = loadImageFromUrl(imageUrl);
  35.                          imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
  36.                          Message message = handler.obtainMessage(0, drawable);
  37.                          handler.sendMessage(message);
  38.                      }
  39.                  }.start();
  40.                  return null;
  41.              }
  42.           
  43.                 public static Drawable loadImageFromUrl(String url) {
  44.                         URL m;
  45.                         InputStream i = null;
  46.                         try {
  47.                                 m = new URL(url);
  48.                                 i = (InputStream) m.getContent();
  49.                         } catch (MalformedURLException e1) {
  50.                                 e1.printStackTrace();
  51.                         } catch (IOException e) {
  52.                                 e.printStackTrace();
  53.                         }
  54.                         Drawable d = Drawable.createFromStream(i, "src");
  55.                         return d;
  56.                 }
  57.           
  58.              public interface ImageCallback {
  59.                  public void imageLoaded(Drawable imageDrawable, String imageUrl);
  60.              }

  61. }
复制代码
以上代码是实现异步获取图片的主方法,SoftReference是软引用,是为了更好的为了系统回收变量,重复的URL直接返回已有的资源,实现回调函数,让数据成功后,更新到UI线程。 
几个辅助类文件:
  1. package cn.wangmeng.test;

  2. public class ImageAndText {
  3.             private String imageUrl;
  4.             private String text;

  5.             public ImageAndText(String imageUrl, String text) {
  6.                 this.imageUrl = imageUrl;
  7.                 this.text = text;
  8.             }
  9.             public String getImageUrl() {
  10.                 return imageUrl;
  11.             }
  12.             public String getText() {
  13.                 return text;
  14.             }
  15. }
复制代码
  1. package cn.wangmeng.test;

  2. import android.view.View;
  3. import android.widget.ImageView;
  4. import android.widget.TextView;

  5. public class ViewCache {

  6.             private View baseView;
  7.             private TextView textView;
  8.             private ImageView imageView;

  9.             public ViewCache(View baseView) {
  10.                 this.baseView = baseView;
  11.             }

  12.             public TextView getTextView() {
  13.                 if (textView == null) {
  14.                     textView = (TextView) baseView.findViewById(R.id.text);
  15.                 }
  16.                 return textView;
  17.             }

  18.             public ImageView getImageView() {
  19.                 if (imageView == null) {
  20.                     imageView = (ImageView) baseView.findViewById(R.id.image);
  21.                 }
  22.                 return imageView;
  23.             }

  24. }
复制代码
ViewCache是辅助获取adapter的子元素布局
  1. package cn.wangmeng.test;

  2. import java.util.List;

  3. import cn.wangmeng.test.AsyncImageLoader.ImageCallback;

  4. import android.app.Activity;
  5. import android.graphics.drawable.Drawable;
  6. import android.view.LayoutInflater;
  7. import android.view.View;
  8. import android.view.ViewGroup;
  9. import android.widget.ArrayAdapter;
  10. import android.widget.ImageView;
  11. import android.widget.ListView;
  12. import android.widget.TextView;

  13. public class ImageAndTextListAdapter extends ArrayAdapter<ImageAndText> {

  14.             private ListView listView;
  15.             private AsyncImageLoader asyncImageLoader;

  16.             public ImageAndTextListAdapter(Activity activity, List<ImageAndText> imageAndTexts, ListView listView) {
  17.                 super(activity, 0, imageAndTexts);
  18.                 this.listView = listView;
  19.                 asyncImageLoader = new AsyncImageLoader();
  20.             }

  21.             public View getView(int position, View convertView, ViewGroup parent) {
  22.                 Activity activity = (Activity) getContext();

  23.                 // Inflate the views from XML
  24.                 View rowView = convertView;
  25.                 ViewCache viewCache;
  26.                 if (rowView == null) {
  27.                     LayoutInflater inflater = activity.getLayoutInflater();
  28.                     rowView = inflater.inflate(R.layout.image_and_text_row, null);
  29.                     viewCache = new ViewCache(rowView);
  30.                     rowView.setTag(viewCache);
  31.                 } else {
  32.                     viewCache = (ViewCache) rowView.getTag();
  33.                 }
  34.                 ImageAndText imageAndText = getItem(position);

  35.                 // Load the image and set it on the ImageView
  36.                 String imageUrl = imageAndText.getImageUrl();
  37.                 ImageView imageView = viewCache.getImageView();
  38.                 imageView.setTag(imageUrl);
  39.                 Drawable cachedImage = asyncImageLoader.loadDrawable(imageUrl, new ImageCallback() {
  40.                     public void imageLoaded(Drawable imageDrawable, String imageUrl) {
  41.                         ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl);
  42.                         if (imageViewByTag != null) {
  43.                             imageViewByTag.setImageDrawable(imageDrawable);
  44.                         }
  45.                     }
  46.                 });
  47.                         if (cachedImage == null) {
  48.                                 imageView.setImageResource(R.drawable.default_image);
  49.                         }else{
  50.                                 imageView.setImageDrawable(cachedImage);
  51.                         }
  52.                 // Set the text on the TextView
  53.                 TextView textView = viewCache.getTextView();
  54.                 textView.setText(imageAndText.getText());

  55.                 return rowView;
  56.             }

  57. }
复制代码
mageAndTextListAdapter是实现ListView的Adapter,里面有个技巧就是imageView.setTag(imageUrl),setTag是存储数据的,这样是为了保证在回调函数时,listview去更新自己对应item,大家仔细阅读就知道了。 
最后贴出布局文件:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.               android:orientation="horizontal"
  4.               android:layout_width="fill_parent"
  5.               android:layout_height="wrap_content">

  6.         <ImageView android:id="@+id/image"
  7.                    android:layout_width="wrap_content"
  8.                    android:layout_height="wrap_content"
  9.                    />

  10.         <TextView android:id="@+id/text"
  11.                   android:layout_width="wrap_content"
  12.                   android:layout_height="wrap_content"/>

  13. </LinearLayout>
复制代码

 AsyncListImage.zip 


没有评论:

发表评论