当前位置: 代码迷 >> Android >> android兑现异步加载图片
  详细解决方案

android兑现异步加载图片

热度:77   发布时间:2016-05-01 17:27:32.0
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()");
??? }
}

1 楼 anyang763 2011-12-01  
2 楼 herozhou1314 2012-04-27  
  相关解决方案