您的位置:首页 > 移动开发 > Android开发

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

2010-12-29 18:08 766 查看
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是实现ListView的Adapter,里面有个技巧就是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()");

}

}

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: