[java]
* 異步加載圖片
* 使用方法:
* private AsyncImageLoader asyImg = new AsyncImageLoader();
* asyImg.LoadImage(productItems.get(position).getPic(), (ImageView)view.findViewById(R.id.pic));
*/
public class AsyncImageLoader {
// 為了加快速度,在內存中開啟緩存(主要應用於重復圖片較多時,或者同一個圖片要多次被訪問,比如在ListView時來回滾動)
public Map<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>();
private ExecutorService executorService = Executors.newFixedThreadPool(5); // 固定五個線程來執行任務
private final Handler handler = new Handler();
// SD卡上圖片儲存地址
private final String path = Environment.getExternalStorageDirectory()
.getPath() + "/maiduo";
/**
*
* @param imageUrl
* 圖像url地址
* @param callback
* 回調接口
* @return 返回內存中緩存的圖像,第一次加載返回null
*/
public Drawable loadDrawable(final String imageUrl,
final ImageCallback callback) {
// 如果緩存過就從緩存中取出數據
if (imageCache.containsKey(imageUrl)) {
SoftReference<Drawable> softReference = imageCache.get(imageUrl);
if (softReference.get() != null) {
return softReference.get();
}
} else if (useTheImage(imageUrl) != null) {
return useTheImage(imageUrl);
}
// 緩存中沒有圖像,則從網絡上取出數據,並將取出的數據緩存到內存中
executorService.submit(new Runnable() {
public void run() {
try {
final Drawable drawable = Drawable.createFromStream(
new URL(imageUrl).openStream(), "image.png");
imageCache.put(imageUrl, new SoftReference<Drawable>(
drawable));
handler.post(new Runnable() {
public void run() {
callback.imageLoaded(drawable);
}
});
saveFile(drawable, imageUrl);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
return null;
}
// 從網絡上取數據方法
public Drawable loadImageFromUrl(String imageUrl) {
try {
return Drawable.createFromStream(new URL(imageUrl).openStream(),
"image.png");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 對外界開放的回調接口
public interface ImageCallback {
// 注意 此方法是用來設置目標對象的圖像資源
public void imageLoaded(Drawable imageDrawable);
}
// 引入線程池,並引入內存緩存功能,並對外部調用封裝了接口,簡化調用過程
public void LoadImage(final String url, final ImageView iv) {
if (iv.getImageMatrix() == null) {
iv.setImageResource(R.drawable.loading);
}
// 如果緩存過就會從緩存中取出圖像,ImageCallback接口中方法也不會被執行
Drawable cacheImage = loadDrawable(url,
new AsyncImageLoader.ImageCallback() {
// 請參見實現:如果第一次加載url時下面方法會執行
public void imageLoaded(Drawable imageDrawable) {
iv.setImageDrawable(imageDrawable);
}
});
if (cacheImage != null) {
iv.setImageDrawable(cacheImage);
}
}
/**
* 保存圖片到SD卡上
*
* @param bm
* @param fileName
*
*/
public void saveFile(Drawable dw, String url) {
try {
BitmapDrawable bd = (BitmapDrawable) dw;
Bitmap bm = bd.getBitmap();
// 獲得文件名字
final String fileNa = url.substring(url.lastIndexOf("/") + 1,
url.length()).toLowerCase();
File file = new File(path + "/image/" + fileNa);
// 創建圖片緩存文件夾
boolean sdCardExist = Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED); // 判斷sd卡是否存在
if (sdCardExist) {
File maiduo = new File(path);
File ad = new File(path + "/image");
// 如果文件夾不存在
if (!maiduo.exists()) {
// 按照指定的路徑創建文件夾
maiduo.mkdir();
// 如果文件夾不存在
} else if (!ad.exists()) {
// 按照指定的路徑創建文件夾
ad.mkdir();
}
// 檢查圖片是否存在
if (!file.exists()) {
file.createNewFile();
}
}
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(file));
bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);
bos.flush();
bos.close();
} catch (Exception e) {
// TODO: handle exception
}
}
/**
* 使用SD卡上的圖片
*
*/
public Drawable useTheImage(String imageUrl) {
Bitmap bmpDefaultPic = null;
// 獲得文件路徑
String imageSDCardPath = path
+ "/image/"
+ imageUrl.substring(imageUrl.lastIndexOf("/") + 1,
imageUrl.length()).toLowerCase();
File file = new File(imageSDCardPath);
// 檢查圖片是否存在
if (!file.exists()) {
return null;
}
bmpDefaultPic = BitmapFactory.decodeFile(imageSDCardPath, null);
if (bmpDefaultPic != null || bmpDefaultPic.toString().length() > 3) {
Drawable drawable = new BitmapDrawable(bmpDefaultPic);
return drawable;
} else
return null;
}
}