[java] package cn.jd3g.utils;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import android.graphics.Bitmap;
import android.os.Handler;
import android.util.Log;
import android.widget.ImageView;
/**
* 利用多線程異步加載圖片並更新視圖
*
* @author xfzhang
*
*/
public final class AsynImageLoader {
private LoaderThread thread;// 加載圖片並發消息通知更新界面的線程
private HashMap<String, SoftReference<Bitmap>> imageCache;// 圖片對象緩存,key:圖片的url
private Handler handler;// 界面Activity的Handler對象
public AsynImageLoader(Handler handler) {
imageCache = new HashMap<String, SoftReference<Bitmap>>();
this.handler = handler;
}
/**
* 加載圖片前顯示到指定的ImageView中,圖片的url保存在視圖對象的Tag中
*
* @param imageView
* 要顯示圖片的視圖
* @param defaultBitmap
* 加載需要顯示的提示正在加載的默認圖片對象
*/
public void loadBitmap(ImageView imageView, Bitmap defaultBitmap) {
// 圖片所對應的url,這個值在加載圖片過程中很可能會被改變
String url = (String) imageView.getTag();
if (imageCache.containsKey(url)) {// 判斷緩存中是否有
SoftReference<Bitmap> softReference = imageCache.get(url);
Bitmap bitmap = softReference.get();
if (bitmap != null) {// 如果圖片對象不為空,則可掛接更新視圖,並返回
imageView.setImageBitmap(bitmap);
return;
} else {// 如果為空,需要將其從緩存中刪除(其bitmap對象已被回收釋放,需要重新加載)
Log.e("TAG", "cache bitmap is null");
imageCache.remove(url);
}
}
imageView.setImageBitmap(defaultBitmap);// 先顯示一個提示正在加載的圖片
if (thread == null) {// 加載線程不存在,線程還未啟動,需要新建線程並啟動
thread = new LoaderThread(imageView, url);
thread.start();
} else {// 如果存在,就調用線程對象去加載
thread.load(imageView, url);
}
}
/**
* 釋放緩存中所有的Bitmap對象,並將緩存清空
*/
public void releaseBitmapCache() {
if (imageCache != null) {
for (Entry<String, SoftReference<Bitmap>> entry : imageCache.entrySet()) {
Bitmap bitmap = entry.getValue().get();
if (bitmap != null) {
bitmap.recycle();// 釋放bitmap對象
}
}
imageCache.clear();
}
}
/**
* 加載圖片並顯示的線程
*/
private class LoaderThread extends Thread {
LinkedHashMap<String, ImageView> mTaskMap;// 需要加載圖片並顯示的圖片視圖對象任務鏈
private boolean mIsWait;// 標識是線程是否處於等待狀態
public LoaderThread(ImageView imageView, String url) {
mTaskMap = new LinkedHashMap<String, ImageView>();
mTaskMap.put(url, imageView);
}
/**
* 處理某個視圖的更新顯示
*
* @param imageView
*/
public void load(ImageView imageView, String url) {
mTaskMap.remove(imageView);// 任務鏈中可能有,得先刪除
mTaskMap.put(url, imageView);// 將其添加到任務中
if (mIsWait) {// 如果線程此時處於等待得喚醒線程去處理任務隊列中待處理的任務
synchronized (this) {// 調用對象的notify()時必須同步
this.notify();
}
}
}
@Override
public void run() {
while (mTaskMap.size() > 0) {// 當隊列中有數據時線程就要一直運行,一旦進入就要保證其不會跳出循環
mIsWait = false;
final String url = mTaskMap.keySet().iterator().next();
final ImageView imageView = mTaskMap.remove(url);
if (imageView.getTag() == url) {// 判斷視圖有沒有復用(一旦ImageView被復用,其tag值就會修改變)
final Bitmap bitmap = MyConnection.getBitmapByUrl(url);// 此方法應該是從網絡或sd卡中加載
try {
Thread.sleep(1000);// 模擬網絡加載數據時間
} catch (InterruptedException e1) {
e1.printStackTrace();
}
// 將加載的圖片放入緩存map中
imageCache.put(url, new SoftReference<Bitmap>(bitmap));
if (url == imageView.getTag()) {// 再次判斷視圖有沒有復用
handler.post(new Runnable() {// 通過消息機制在主線程中更新UI
@Override
public void run() {
imageView.setImageBitmap(bitmap);
}
});
}
}
if (mTaskMap.isEmpty()) {// 當任務隊列中沒有待處理的任務時,線程進入等待狀態
try {
mIsWait = true;// 標識線程的狀態,必須在wait()方法之前
synchronized (this) {
this.wait();// 保用線程進入等待狀態,直到有新的任務被加入時通知喚醒
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
package cn.jd3g.utils;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import android.graphics.Bitmap;
import android.os.Handler;
import android.util.Log;
import android.widget.ImageView;
/**
* 利用多線程異步加載圖片並更新視圖
*
* @author xfzhang
*
*/
public final class AsynImageLoader {
private LoaderThread thread;// 加載圖片並發消息通知更新界面的線程
private HashMap<String, SoftReference<Bitmap>> imageCache;// 圖片對象緩存,key:圖片的url
private Handler handler;// 界面Activity的Handler對象
public AsynImageLoader(Handler handler) {
imageCache = new HashMap<String, SoftReference<Bitmap>>();
this.handler = handler;
}
/**
* 加載圖片前顯示到指定的ImageView中,圖片的url保存在視圖對象的Tag中
*
* @param imageView
* 要顯示圖片的視圖 www.aiwalls.com
* @param defaultBitmap
* 加載需要顯示的提示正在加載的默認圖片對象
*/
public void loadBitmap(ImageView imageView, Bitmap defaultBitmap) {
// 圖片所對應的url,這個值在加載圖片過程中很可能會被改變
String url = (String) imageView.getTag();
if (imageCache.containsKey(url)) {// 判斷緩存中是否有
SoftReference<Bitmap> softReference = imageCache.get(url);
Bitmap bitmap = softReference.get();
if (bitmap != null) {// 如果圖片對象不為空,則可掛接更新視圖,並返回
imageView.setImageBitmap(bitmap);
return;
} else {// 如果為空,需要將其從緩存中刪除(其bitmap對象已被回收釋放,需要重新加載)
Log.e("TAG", "cache bitmap is null");
imageCache.remove(url);
}
}
imageView.setImageBitmap(defaultBitmap);// 先顯示一個提示正在加載的圖片
if (thread == null) {// 加載線程不存在,線程還未啟動,需要新建線程並啟動
thread = new LoaderThread(imageView, url);
thread.start();
} else {// 如果存在,就調用線程對象去加載
thread.load(imageView, url);
}
}
/**
* 釋放緩存中所有的Bitmap對象,並將緩存清空
*/
public void releaseBitmapCache() {
if (imageCache != null) {
for (Entry<String, SoftReference<Bitmap>> entry : imageCache.entrySet()) {
Bitmap bitmap = entry.getValue().get();
if (bitmap != null) {
bitmap.recycle();// 釋放bitmap對象
}
}
imageCache.clear();
}
}
/**
* 加載圖片並顯示的線程
*/
private class LoaderThread extends Thread {
LinkedHashMap<String, ImageView> mTaskMap;// 需要加載圖片並顯示的圖片視圖對象任務鏈
private boolean mIsWait;// 標識是線程是否處於等待狀態
public LoaderThread(ImageView imageView, String url) {
mTaskMap = new LinkedHashMap<String, ImageView>();
mTaskMap.put(url, imageView);
}
/**
* 處理某個視圖的更新顯示
*
* @param imageView
*/
public void load(ImageView imageView, String url) {
mTaskMap.remove(imageView);// 任務鏈中可能有,得先刪除
mTaskMap.put(url, imageView);// 將其添加到任務中
if (mIsWait) {// 如果線程此時處於等待得喚醒線程去處理任務隊列中待處理的任務
synchronized (this) {// 調用對象的notify()時必須同步
this.notify();
}
}
}
@Override
public void run() {
while (mTaskMap.size() > 0) {// 當隊列中有數據時線程就要一直運行,一旦進入就要保證其不會跳出循環
mIsWait = false;
final String url = mTaskMap.keySet().iterator().next();
final ImageView imageView = mTaskMap.remove(url);
if (imageView.getTag() == url) {// 判斷視圖有沒有復用(一旦ImageView被復用,其tag值就會修改變)
final Bitmap bitmap = MyConnection.getBitmapByUrl(url);// 此方法應該是從網絡或sd卡中加載
try {
Thread.sleep(1000);// 模擬網絡加載數據時間
} catch (InterruptedException e1) {
e1.printStackTrace();
}
// 將加載的圖片放入緩存map中
imageCache.put(url, new SoftReference<Bitmap>(bitmap));
if (url == imageView.getTag()) {// 再次判斷視圖有沒有復用
handler.post(new Runnable() {// 通過消息機制在主線程中更新UI
@Override
public void run() {
imageView.setImageBitmap(bitmap);
}
});
}
}
if (mTaskMap.isEmpty()) {// 當任務隊列中沒有待處理的任務時,線程進入等待狀態
try {
mIsWait = true;// 標識線程的狀態,必須在wait()方法之前
synchronized (this) {
this.wait();// 保用線程進入等待狀態,直到有新的任務被加入時通知喚醒
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}自定義的adapter
[java] private class ProductListAdapter extends BaseAdapter {
private AsynImageLoader mImageAsynLoader;
public ProductListAdapter() {
mImageAsynLoader = new AsynImageLoader(mHandler);
}
@Override
public int getCount() {
int size = Math.min(mLastItemViewIndex + 1, mDataList.size());
mLastItemViewIndex = size – 1;
return size;
}
@Override
public Object getItem(int position) {
return mDataList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = getLayoutInflater().inflate(R.layout.product_list_item,
null);
}
ImageView imageView = (ImageView) convertView
.findViewById(R.id.iv_item_product_image);
Map<String, String> map = mDataList.get(position);
//存放圖片所對應的url
imageView.setTag(map.get("product_pic_address"));
mImageAsynLoader.loadBitmap(imageView, mDefautBitmap);
return convertView;
}
}
private class ProductListAdapter extends BaseAdapter {
private AsynImageLoader mImageAsynLoader;
public ProductListAdapter() {
mImageAsynLoader = new AsynImageLoader(mHandler);
}
@Override
public int getCount() {
int size = Math.min(mLastItemViewIndex + 1, mDataList.size());
mLastItemViewIndex = size – 1;
return size;
}
@Override
public Object getItem(int position) {
return mDataList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = getLayoutInflater().inflate(R.layout.product_list_item,
null);
}
ImageView imageView = (ImageView) convertView
.findViewById(R.id.iv_item_product_image);
Map<String, String> map = mDataList.get(position);
//存放圖片所對應的url
imageView.setTag(map.get("product_pic_address"));
mImageAsynLoader.loadBitmap(imageView, mDefautBitmap);
return convertView;
}
}
摘自 agods–足跡