Android ListView 異步加載圖片

ListView異步加載圖片是非常實用的方法,凡是是要通過網絡獲取圖片資源一般使用這種方法比較好,用戶體驗好,下面就說實現方法,先貼上主方法的代碼:

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);
     }

}</pre>以上代碼是實現異步獲取圖片的主方法,SoftReference是軟引用,是為了更好的為了系統回收變量,重復的URL直接返回已有的資源,實現回調函數,讓數據成功后,更新到UI線程。
幾個輔助類文件:

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;
    }

}</pre>

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;
    }

}</pre>ViewCache是輔助獲取adapter的子元素布局

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;
    }

}</pre>ImageAndTextListAdapter是實現ListView的Adapter,里面有個技巧就是imageView.setTag(imageUrl),setTag是存儲數據的,這樣是為了保證在回調函數時,listview去更新自己對應item,大家仔細閱讀就知道了。
最后貼出布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="

    <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></pre>

 本文由用戶 mark0614 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!