package com.ejoy.adpter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import com.ejoy.utils.BitmapUtils;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;
public class AsyncBitmapLoader {
/**
* 内存图片软引用缓冲
*/
private HashMap<String, SoftReference<Bitmap>> imageCache = null;
public AsyncBitmapLoader() {
imageCache = new HashMap<String, SoftReference<Bitmap>>();
}
protected String GetDatabasePath(String name) {
String EXTERN_PATH = null;
if (com.ejoy.FileServer.SDCardOperation.CanSdCardUse()) {
EXTERN_PATH = android.os.Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/ejoy/cache/";
File f = new File(EXTERN_PATH);
if (!f.exists()) {
f.mkdirs();
}
}
if (name.trim() == "") {
return EXTERN_PATH;
} else {
return EXTERN_PATH + name;
}
}
public Bitmap loadBitmap(final ImageView imageView, final String imageURL,
final ImageCallBack imageCallBack) {
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
imageCallBack.imageLoad(imageView, (Bitmap) msg.obj);
}
};
if (imageURL.trim() == "") {
handler.sendMessage(handler.obtainMessage(0, null));
}
final String FileName = imageURL
.substring(imageURL.lastIndexOf("/") + 1);
// 在内存缓存中,则返回Bitmap对象
if (imageCache.containsKey(imageURL)) {
SoftReference<Bitmap> reference = imageCache.get(imageURL);
Bitmap bitmap = reference.get();
if (bitmap != null) {
handler.sendMessage(handler.obtainMessage(0, bitmap));
return bitmap;
}
} else {
/**
* 加上一个对本地缓存的查找
*/
File cacheDir = new File(GetDatabasePath(""));
File[] cacheFiles = cacheDir.listFiles();
int i = 0;
int j = cacheFiles.length;
for (; i < j; i++) {
if (FileName.equals(cacheFiles[i].getName())
&& cacheFiles[i].length() > 0) {
break;
}
}
if (i < cacheFiles.length) {
String path = GetDatabasePath(FileName);
Bitmap bitmap;
try {
bitmap = BitmapUtils.getBitmapByPath(path,
BitmapUtils.getOptions(path), 90, 90);
} catch (FileNotFoundException e) {
bitmap = null;
}
handler.sendMessage(handler.obtainMessage(0, bitmap));
return bitmap;
}
}
// 如果不在内存缓存中,也不在本地(被jvm回收掉),则开启线程下载图片
new Thread() {
@Override
public void run() {
URL url;
Bitmap bitmap = null;
try {
if (imageURL.trim() != "" && FileName.trim() != "") {
url = new URL(imageURL);
URLConnection conn = url.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream bitmapIs = conn.getInputStream();
bitmap = BitmapFactory.decodeStream(bitmapIs);
imageCache.put(imageURL, new SoftReference<Bitmap>(
bitmap));
File bitmapFile = new File(GetDatabasePath(FileName));
if (!bitmapFile.isDirectory()) {
if (!bitmapFile.exists()) {
bitmapFile.createNewFile();
} else {
if (bitmapFile.length() == 0) {
bitmapFile.delete();
bitmapFile.createNewFile();
}
}
FileOutputStream fos;
try {
fos = new FileOutputStream(bitmapFile);
if (fos != null) {
bitmap.compress(Bitmap.CompressFormat.JPEG,
100, fos);
fos.close();
}
} catch (FileNotFoundException e) {
} catch (IOException e) {
e.printStackTrace();
}
}
bitmapIs.close();
} else {
}
} catch (FileNotFoundException e) {
} catch (Exception e1) {
e1.printStackTrace();
}
Message msg = handler.obtainMessage(0, bitmap);
handler.sendMessage(msg);
}
}.start();
return null;
}
/**
* 回调接口
*
* @author onerain
*
*/
public interface ImageCallBack {
public void imageLoad(ImageView imageView, Bitmap bitmap);
}
}
2012-08-22 修改一个开源的ListView加载图片类
1.加上图片的本地sd卡查找
2.ListView列表项目改成默认图片的显示
package com.ejoy.adpter;
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 com.ejoy.android.R;
import com.ejoy.utils.BitmapUtils;
import com.ejoy.utils.MD5;
import com.ejoy.utils.StringUtils;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.http.AndroidHttpClient;
import android.os.AsyncTask;
import android.os.Handler;
import android.util.Log;
import android.widget.ImageView;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
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.LinkedHashMap;
import java.util.concurrent.ConcurrentHashMap;
public class ImageDownloader {
private static final String LOG_TAG = "ImageDownloader";
private static Context mContext;
@SuppressWarnings("static-access")
public ImageDownloader(final Context mContext) {
this.mContext = mContext;
}
public void download(String url, ImageView imageView) {
resetPurgeTimer();
Bitmap bitmap = getBitmapFromCache(url);
if (bitmap == null) {
forceDownload(url, imageView);
} else {
cancelPotentialDownload(url, imageView);
imageView.setImageBitmap(bitmap);
}
}
private void forceDownload(String url, ImageView imageView) {
if (url == null) {
imageView.setImageResource(R.drawable.defaultbj2);
return;
}
if (cancelPotentialDownload(url, imageView)) {
BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);
imageView.setImageDrawable(downloadedDrawable);
imageView.setMinimumHeight(156);
task.execute(url);
}
}
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 {
return false;
}
}
return true;
}
/**
* @param imageView
* Any imageView
* @return Retrieve the currently active download task (if any) associated
* with this imageView. null if there is no such task.
*/
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 HttpClient client = 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) {
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
inputStream = entity.getContent();
Bitmap bitmap = BitmapFactory
.decodeStream(new FlushedInputStream(inputStream));
saveFile(bitmap, url);
return bitmap;
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
} catch (IOException e) {
getRequest.abort();
// Log.w(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;
}
/**
* 保存文件
*
* @param bm
* @param fileName
* @throws IOException
*/
public void saveFile(Bitmap bm, String url) {
try {
if (com.ejoy.FileServer.SDCardOperation.CanSdCardUse()) {
String EXTERN_PATH = android.os.Environment
.getExternalStorageDirectory().getAbsolutePath()
+ "/ejoy/cache/";
File myCaptureFile = new File(EXTERN_PATH + MD5.getMD5(url));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(myCaptureFile));
bm.compress(Bitmap.CompressFormat.JPEG, 80, bos);
bos.flush();
bos.close();
}
} catch (Exception e) {
//e.printStackTrace();
}
}
/*
* An InputStream that skips the exact number of bytes provided, unless it
* reaches EOF.
*/
static class FlushedInputStream extends FilterInputStream {
public FlushedInputStream(InputStream inputStream) {
super(inputStream);
}
@Override
public long skip(long n) throws IOException {
long totalBytesSkipped = 0L;
while (totalBytesSkipped < n) {
long bytesSkipped = in.skip(n - totalBytesSkipped);
if (bytesSkipped == 0L) {
int b = read();
if (b < 0) {
break; // we reached EOF
} else {
bytesSkipped = 1; // we read one byte
}
}
totalBytesSkipped += bytesSkipped;
}
return totalBytesSkipped;
}
}
/**
* The actual AsyncTask that will asynchronously download the image.
*/
class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
private String url;
private final WeakReference<ImageView> imageViewReference;
public BitmapDownloaderTask(ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView);
}
/**
* Actual download method.
*/
@Override
protected Bitmap doInBackground(String... params) {
url = params[0];
return downloadBitmap(url);
}
/**
* Once the image is downloaded, associates it to the imageView
*/
@Override
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)) {
imageView.setImageBitmap(bitmap);
}
}
}
}
/**
* A fake Drawable that will be attached to the imageView while the download
* is in progress.
*
* <p>
* Contains a reference to the actual download task, so that a download task
* can be stopped if a new binding is required, and makes sure that only the
* last started download process can bind its result, independently of the
* download finish order.
* </p>
*/
static class DownloadedDrawable extends BitmapDrawable {
private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;
public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
super(BitmapFactory.decodeResource(mContext.getResources(),
R.drawable.defaultbj2));
bitmapDownloaderTaskReference = new WeakReference<BitmapDownloaderTask>(
bitmapDownloaderTask);
}
public BitmapDownloaderTask getBitmapDownloaderTask() {
return bitmapDownloaderTaskReference.get();
}
}
/*
* Cache-related fields and methods.
*
* We use a hard and a soft cache. A soft reference cache is too
* aggressively cleared by the Garbage Collector.
*/
private static final int HARD_CACHE_CAPACITY = 10;
private static final int DELAY_BEFORE_PURGE = 10 * 1000; // in milliseconds
// Hard cache, with a fixed maximum capacity and a life duration
@SuppressWarnings("serial")
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;
}
};
// Soft cache for bitmaps kicked out of hard cache
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();
}
};
/**
* Adds this bitmap to the cache.
*
* @param bitmap
* The newly downloaded bitmap.
*/
private void addBitmapToCache(String url, Bitmap bitmap) {
if (bitmap != null) {
synchronized (sHardBitmapCache) {
sHardBitmapCache.put(url, bitmap);
}
}
}
/**
* @param url
* The URL of the image that will be retrieved from the cache.
* @return The cached bitmap or null if it was not found.
*/
private Bitmap getBitmapFromCache(String url) {
// First try the hard reference cache
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);
}
}
try {
// 加上文件的查找
if (com.ejoy.FileServer.SDCardOperation.CanSdCardUse()) {
String EXTERN_PATH = android.os.Environment
.getExternalStorageDirectory().getAbsolutePath()
+ "/ejoy/cache/" + MD5.getMD5(url);
File f = new File(EXTERN_PATH);
if (f.exists()) {
return BitmapFactory.decodeFile(EXTERN_PATH);
}
}
} catch (Exception e) {
// TODO: handle exception
}
return null;
}
/**
* Clears the image cache used internally to improve performance. Note that
* for memory efficiency reasons, the cache will automatically be cleared
* after a certain inactivity delay.
*/
public void clearCache() {
sHardBitmapCache.clear();
sSoftBitmapCache.clear();
}
/**
* Allow a new delay before the automatic cache clear is done.
*/
private void resetPurgeTimer() {
purgeHandler.removeCallbacks(purger);
purgeHandler.postDelayed(purger, DELAY_BEFORE_PURGE);
}
}