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

来源:互联网 发布:java websocket实例 编辑:程序博客网 时间:2024/04/29 09:04

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  DrawableloadDrawable( final  String imageUrl,  final  ImageCallbackimageCallback) {
            
 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  DrawableloadImageFromUrl(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(DrawableimageDrawable, 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  AsyncImageLoaderasyncImageLoader;

       
 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 viewsfrom 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 andset 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(DrawableimageDrawable, String imageUrl) {
                    ImageViewimageViewByTag
 =  (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 theTextView
           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 fromthe 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 imagesis 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(Stringurl, 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 = newBitmapDownloaderTask(imageview);
                DownloadedDrawabledownloadedDrawable = new DownloadedDrawable(
                        task);
               imageview.setImageDrawable(downloadedDrawable);
               imageview.setMinimumHeight(156);
                task.execute(url);
                break;
            }
        }
    }

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

    private static BitmapDownloaderTaskgetBitmapDownloaderTask(
            ImageView imageview) {
        if (imageview != null) {
            Drawable drawable =imageview.getDrawable();
            if (drawable instanceofDownloadedDrawable) {
                DownloadedDrawabledownloadedDrawable = (DownloadedDrawable) drawable;
                returndownloadedDrawable.getBitmapDownloaderTask();
            }
        }
        return null;
    }

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

                InputStream inputStream =null;
                try {
                    inputStream = entity.getContent();
                    returnBitmapFactory.decodeStream(new FlushedInputStream(
                           inputStream));
                } finally {
                    if (inputStream !=null) {
                        inputStream.close();
                    }
                   entity.consumeContent();
                }
            }
        } catch (IOException e) {
            getRequest.abort();
            Log.v(LOG_TAG, "I/Oerror 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, "Errorwhile retrieving bitmap from " + url, e);
        } finally {
            if ((client instanceofAndroidHttpClient)) {
                ((AndroidHttpClient)client).close();
            }
        }
        return null;
    }

    static class FlushedInputStreamextends FilterInputStream {
        publicFlushedInputStream(InputStream inputStream) {
            super(inputStream);
        }

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

    class BitmapDownloaderTask extendsAsyncTask<String, Void, Bitmap> {
        private String url;
        private finalWeakReference<ImageView> imageViewReference;

        publicBitmapDownloaderTask(ImageView imageview) {
            imageViewReference = newWeakReference<ImageView>(imageview);

        }

        @Override
        protected BitmapdoInBackground(String... params) {
            // TODO Auto-generated methodstub
            url = params[0];
            return downloadBitmap(url);
        }

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

    static class DownloadedDrawableextends ColorDrawable {
        private finalWeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;

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

        public BitmapDownloaderTaskgetBitmapDownloaderTask() {
            returnbitmapDownloaderTaskReference.get();
        }
    }

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

    private static final intHARD_CACHE_CAPACITY = 10;
    private static final intDELAY_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 ofhard reference cache are transferred to
                // soft reference cache
                sSoftBitmapCache.put(eldest.getKey(),
                        newSoftReference<Bitmap>(eldest.getValue()));
                return true;
            } else
                return false;
        }
    };

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

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

    private BitmapgetBitmapFromCache(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 = newURL(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(Voidresult) {
        Log.v(TAG,"onPostExecute()");
    }
}
*/

 

原创粉丝点击