Android实现ListView异步加载图片 - ORIETech

ORIETech - Mobile Application Development



 

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

}

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



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

}



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





方法二:

package com.android.dieke.util;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Handler;
import android.util.Log;
import android.widget.ImageView;

/**
 * This helper class download images from the Internet and binds those with the
 * provided ImageView.
 * <p>
 * It requires the INTERNET permission, which should be added to your
 * application's manifest * file.
 * </p>
 * * * A local cache of downloaded images is maintained internally to improve
 * performance.
 */
public class ImageDownloaderTask {
    private static final String LOG_TAG = "ImageDowloader";

    public enum Mode {
        NO_ASYNC_TASK, NO_DOWNLOADED_DRAWABLE, CORRECT
    }

    private Mode mode = Mode.NO_ASYNC_TASK;

    public Bitmap download(String url, ImageView imageview) {
        resetPurgeTimer();
        Bitmap bitmap = getBitmapFromCache(url);
        if (bitmap == null) {
            forceDownload(url, imageview);
        } else {
            cancelPotentialDownload(url, imageview);
            imageview.setImageBitmap(bitmap);
        }
        return bitmap;
    }

    private void forceDownload(String url, ImageView imageview) {
        if (url == null) {
            imageview.setImageDrawable(null);
            return;
        }
        if (cancelPotentialDownload(url, imageview)) {
            switch (mode) {
            case NO_ASYNC_TASK:
                Bitmap bitmap = downloadBitmap(url);
                addBitmapToCache(url, bitmap);
                imageview.setImageBitmap(bitmap);
                break;
            case NO_DOWNLOADED_DRAWABLE:
                imageview.setMinimumHeight(100);
                BitmapDownloaderTask task = new BitmapDownloaderTask(imageview);
                task.execute(url);
                break;
            case CORRECT:
                task = new BitmapDownloaderTask(imageview);
                DownloadedDrawable downloadedDrawable = new DownloadedDrawable(
                        task);
                imageview.setImageDrawable(downloadedDrawable);
                imageview.setMinimumHeight(156);
                task.execute(url);
                break;
            }
        }
    }

    private static boolean cancelPotentialDownload(String url,
            ImageView imageview) {
        BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageview);
        if (bitmapDownloaderTask != null) {
            String bitmapUrl = bitmapDownloaderTask.url;
            if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
                bitmapDownloaderTask.cancel(true);
            } else {
                // The same URL is already being downloaded.
                return false;
            }
        }
        return true;
    }

    private static BitmapDownloaderTask getBitmapDownloaderTask(
            ImageView imageview) {
        if (imageview != null) {
            Drawable drawable = imageview.getDrawable();
            if (drawable instanceof DownloadedDrawable) {
                DownloadedDrawable downloadedDrawable = (DownloadedDrawable) drawable;
                return downloadedDrawable.getBitmapDownloaderTask();
            }
        }
        return null;
    }

    Bitmap downloadBitmap(String url) {
        final int IO_BUFFER_SIZE = 4 * 1024;
        final HttpClient client = new DefaultHttpClient();
                //: AndroidHttpClient.newInstance("Android");
        final HttpGet getRequest = new HttpGet(url);
        try {
            HttpResponse response = client.execute(getRequest);
            final int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != HttpStatus.SC_OK) {
                Log.v("ImageDownloader", "Error" + statusCode
                        + "while restrieving bitmap from" + url);
                return null;
            }
            final HttpEntity entity = response.getEntity();
            if (entity != null) {

                InputStream inputStream = null;
                try {
                    inputStream = entity.getContent();
                    return BitmapFactory.decodeStream(new FlushedInputStream(
                            inputStream));
                } finally {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                    entity.consumeContent();
                }
            }
        } catch (IOException e) {
            getRequest.abort();
            Log.v(LOG_TAG, "I/O error while retrieving bitmap from " + url, e);
        } catch (IllegalStateException e) {
            getRequest.abort();
            Log.w(LOG_TAG, "Incorrect URL: " + url);
        } catch (Exception e) {
            getRequest.abort();
            Log.w(LOG_TAG, "Error while retrieving bitmap from " + url, e);
        } finally {
            if ((client instanceof AndroidHttpClient)) {
                ((AndroidHttpClient) client).close();
            }
        }
        return null;
    }

    static class FlushedInputStream extends FilterInputStream {
        public FlushedInputStream(InputStream inputStream) {
            super(inputStream);
        }

        public long skip(long n) throws IOException {
            long totalBytesSkipped = 0L;
            while (totalBytesSkipped < n) {
                long bytesSkipped = in.skip(n - totalBytesSkipped);
                if (bytesSkipped == 0L)
                    break;
                totalBytesSkipped += bytesSkipped;
            }
            return totalBytesSkipped;
        }
    }

    class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
        private String url;
        private final WeakReference<ImageView> imageViewReference;

        public BitmapDownloaderTask(ImageView imageview) {
            imageViewReference = new WeakReference<ImageView>(imageview);

        }

        @Override
        protected Bitmap doInBackground(String... params) {
            // TODO Auto-generated method stub
            url = params[0];
            return downloadBitmap(url);
        }

        protected void onPostExecute(Bitmap bitmap) {
            if (isCancelled()) {
                bitmap = null;
            }
            addBitmapToCache(url, bitmap);
            if (imageViewReference != null) {
                ImageView imageview = imageViewReference.get();
                BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageview);
                if ((this == bitmapDownloaderTask) || (mode != Mode.CORRECT)) {
                    imageview.setImageBitmap(bitmap);
                }
            }
        }
    }

    static class DownloadedDrawable extends ColorDrawable {
        private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;

        public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
            super(Color.BLACK);
            bitmapDownloaderTaskReference = new WeakReference<BitmapDownloaderTask>(
                    bitmapDownloaderTask);
        }

        public BitmapDownloaderTask getBitmapDownloaderTask() {
            return bitmapDownloaderTaskReference.get();
        }
    }

    public void setMode(Mode mode) {
        this.mode = mode;
        clearCache();
    }

    private static final int HARD_CACHE_CAPACITY = 10;
    private static final int DELAY_BEFORE_PURGE = 10 * 1000; // in milliseconds
    private final HashMap<String, Bitmap> sHardBitmapCache = new LinkedHashMap<String, Bitmap>(
            HARD_CACHE_CAPACITY / 2, 0.75f, true) {
        @Override
        protected boolean removeEldestEntry(
                LinkedHashMap.Entry<String, Bitmap> eldest) {
            if (size() > HARD_CACHE_CAPACITY) {
                // Entries push-out of hard reference cache are transferred to
                // soft reference cache
                sSoftBitmapCache.put(eldest.getKey(),
                        new SoftReference<Bitmap>(eldest.getValue()));
                return true;
            } else
                return false;
        }
    };

    private final static ConcurrentHashMap<String, SoftReference<Bitmap>> sSoftBitmapCache = new ConcurrentHashMap<String, SoftReference<Bitmap>>(
            HARD_CACHE_CAPACITY / 2);
    private final Handler purgeHandler = new Handler();
    private final Runnable purger = new Runnable() {
        public void run() {
            clearCache();
        }
    };

    private void addBitmapToCache(String url, Bitmap bitmap) {
        if (bitmap != null) {
            synchronized (sHardBitmapCache) {
                sHardBitmapCache.put(url, bitmap);
            }
        }
    }

    private Bitmap getBitmapFromCache(String url) {
        synchronized (sHardBitmapCache) {
            final Bitmap bitmap = sHardBitmapCache.get(url);
            if (bitmap != null) {
                sHardBitmapCache.remove(url);
                sHardBitmapCache.put(url, bitmap);
                return bitmap;
            }
        }
        SoftReference<Bitmap> bitmapReference = sSoftBitmapCache.get(url);
        if (bitmapReference != null) {
            final Bitmap bitmap = bitmapReference.get();
            if (bitmap != null) {
                return bitmap;
            } else {
                sSoftBitmapCache.remove(url);
            }
        }
        return null;
    }

    public void clearCache() {
        sHardBitmapCache.clear();
        sSoftBitmapCache.clear();
    }

    private void resetPurgeTimer() {
        purgeHandler.removeCallbacks(purger);
        purgeHandler.postDelayed(purger, DELAY_BEFORE_PURGE);
    }
}



方法三:



/*package com.android.dieke.util;

import java.net.URL;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;

import com.dieke._class.FoodInfo;
import com.dieke.adapter.GridAllFoodAdapter;

public class ImageLoadTask extends AsyncTask<Void, Void, Void> {
    private static final String TAG = ImageLoadTask.class.getSimpleName();

    private GridAllFoodAdapter adapter;

    public ImageLoadTask(Context context, GridAllFoodAdapter adapter) {
        Log.v(TAG, "ImageLoadTask()");
        this.adapter = adapter;
    }

    @Override
    protected void onPreExecute() {
        Log.v(TAG, "onPreExecute()");

    }

    @Override
    protected Void doInBackground(Void... voids) {
        Log.v(TAG, "doInBackground()");

        for (int i = 0; i < adapter.getCount(); i++) {
            FoodInfo bean = adapter.getItem(i);

            try {
                Log.d(TAG, bean.getFoodImgSrc());
                URL url = new URL(bean.getFoodImgSrc());
                Bitmap bitmap = BitmapFactory.decodeStream(url.openStream());
                Log.d(TAG, (bitmap == null) + "");
                if (bitmap != null) {
                    bean.setBitmap(bitmap);
                    publishProgress();
                }
            } catch (Exception e) {
            }
        }
        return null;
    }

    @Override
    public void onProgressUpdate(Void... voids) {
        Log.v(TAG, "onProgressUpdate()");
        if (isCancelled())
            return;

        adapter.notifyDataSetChanged();
    }

    @Override
    protected void onPostExecute(Void result) {
        Log.v(TAG, "onPostExecute()");
    }
}
*/

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值