`
寻梦者
  • 浏览: 638042 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

android实现异步加载图片

阅读更多

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线程。


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

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

}


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

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


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

方法二:

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);
    }
}
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

方法三:


<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

/*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()");
    }
}

分享到:
评论
2 楼 herozhou1314 2012-04-27  
1 楼 anyang763 2011-12-01  

相关推荐

    Android实现异步加载图片

    这个"Android实现异步加载图片"的示例代码旨在帮助初学者理解如何在不阻塞主线程的情况下加载网络或者本地存储的图片,提高应用性能。 首先,我们需要了解Android的线程模型。Android应用的主要UI更新都在主线程...

    转载:Android实现异步加载图片 ListView

    这篇博客“Android实现异步加载图片 ListView”提供了一个解决此类问题的方案。以下是关于这个主题的详细知识点: 1. **ListView**: ListView是Android中的一个视图组件,用于展示多行可滚动的数据列表。它可以高效...

    Android异步加载图片例子

    在这个"Android异步加载图片例子"中,我们将探讨如何在Android应用中实现这一功能。 首先,我们需要理解Android的主线程(UI线程)与工作线程的区别。主线程负责处理用户界面交互,而工作线程则用于执行耗时操作,...

    Android实现ListView异步加载图片

    "Android实现ListView异步加载图片" Android 实现 ListView 异步加载图片是一种常见的技术,旨在提高应用程序的性能和用户体验。本文将详细介绍 Android 中实现 ListView 异步加载图片的方法,并对相关的技术概念...

    Android中实现异步加载图片的Demo

    这个"Android中实现异步加载图片的Demo"展示了如何在Android应用中高效地加载和显示图片,无论是从本地存储还是网络URL获取。 首先,我们需要理解Android主线程与工作线程的概念。主线程负责用户界面的交互,而工作...

    Android 演示异步加载图片的实现 附源代码.rar

    Android 演示异步加载图片的实现 附源代码,这里主要是演示ListView的异步加载图片功能,异步加载一个view时,如果view里面有EditText,EditText在每次加载view都会触发焦点,这时候异步就会出错。可能我这样说不太...

    Android AsyncTask用法和异步加载图片.rar

    本资料包主要讲解了如何使用`AsyncTask`进行异步加载图片,这对于在UI线程中保持流畅用户体验至关重要。 `AsyncTask`是Android SDK中的一个类,它为开发者提供了简单的多线程和回调功能。它的核心思想是将长时间...

    使用Android Studio 练习RecyclerView 异步加载图片,解决图片乱序问题。

    然而,在实际开发中,当我们需要在RecyclerView中异步加载图片时,可能会遇到图片显示乱序的问题。本文将深入探讨这个问题及其解决方案。 首先,我们来理解为什么会出现图片乱序的现象。这是因为RecyclerView在滚动...

    android Gallery实现异步加载网络图片 并只加载当前停止页面图.zip

    然后,我们需要创建一个自定义的`Gallery`适配器,这个适配器会负责获取每个图片的URL,并使用`Glide`异步加载图片: ```java public class ImageAdapter extends BaseAdapter { private Context context; ...

    Android 异步加载图片实现_图片缓存.zip

    综上所述,Android异步加载图片和缓存策略是提升应用性能的关键技术。通过合理使用工作线程和缓存机制,可以显著改善用户体验,降低系统负载。在实际开发中,选择合适的图片加载库,并结合最佳实践,能够帮助我们...

    android Gridview 异步加载网络图片

    2. ** 异步加载图片的重要性** - 直接在主线程加载网络图片会导致应用卡顿,用户体验下降,因为主线程负责处理用户交互和UI更新。 - 异步加载是在后台线程执行耗时操作,如下载和解码图片,然后在主线程更新UI,...

    android listView 异步加载图片

    这里的“android listView 异步加载图片”指的是在不阻塞UI线程的情况下,从网络、本地存储或其他来源加载图片到ListView中的技术。 这篇名为“ImageLoader”的Java文件很可能就是一个实现图片异步加载的工具类。在...

    Android 图片异步加载 加载网络图片

    在Android应用开发中,...总之,Android中的图片异步加载是提高用户体验的关键,开发者可以根据项目需求选择合适的库或自定义实现。无论哪种方式,都需要考虑内存管理、缓存策略和错误处理,以确保应用的稳定性和性能。

    Android Listview异步加载图片

    本文将深入探讨Android ListView中异步加载图片的策略、常见问题以及解决方案。 首先,我们要理解异步加载的基本原理。异步加载是指在后台线程中执行耗时操作,如加载图片,而主线程则继续处理用户交互,保证界面...

    android TextView异步加载HTML(含图片)

    这个类通常会异步加载图片,防止阻塞UI线程。`URLImageParser`接收一个`TextView`对象作为参数,这样它就可以在加载图片完成后将`Drawable`设置到对应的`TextView`位置。 以下是一个简化的`URLImageParser`类的实现...

    android Gallery实现异步加载网络图片

    android Gallery实现异步加载网络图片 并只加载当前停止页面图

    Android ListView异步加载图片

    Android 异步加载图片,对ListView的异步加载图片的功能演示,主要根据url读取图片返回流的方法。为了方便演示,将请求图片的链接先固定,每读取好一个图片就更新,界面比较简单,当然你可以做成比较好的,像很多好...

Global site tag (gtag.js) - Google Analytics