import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
import com.siso.dy.buyenough.constant.Constant;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
import android.media.ThumbnailUtils;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.support.v4.util.LruCache;
import android.text.TextUtils;
import android.widget.ImageView;
/**
* 图片加载类
*/
public class ImageLoader {
private static ImageLoader instance;
public LruCache<String, Bitmap> mMemoryCache;
/** 图片加载队列,后进先出 */
private Stack<ImageRef> mImageQueue = new Stack<ImageRef>();
/** 图片请求队列,先进先出,用于存放已发送的请求。 */
private Queue<ImageRef> mRequestQueue = new LinkedList<ImageRef>();
/** 图片加载线程消息处理器 */
private Handler mImageLoaderHandler;
/** 图片加载线程是否就绪 */
private boolean mImageLoaderIdle = true;
/** 请求图片 */
private static final int MSG_REQUEST = 1;
/** 图片加载完成 */
private static final int MSG_REPLY = 2;
/** 中止图片加载线程 */
private static final int MSG_STOP = 3;
/** 如果图片是从网络加载,则应用渐显动画,如果从缓存读出则不应用动画 */
private boolean isFromNet = true;
private static final String CACHE_PATH = Environment
.getExternalStoragePublicDirectory(Constant.IMGURL)
.getAbsolutePath();
/**
* 获取单例,只能在UI线程中使用。
*
* @return
*/
public static ImageLoader getInst() {
// 如果不在ui线程中,则抛出异常
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new RuntimeException("Cannot instantiate outside UI thread.");
}
if (instance == null) {
synchronized (ImageLoader.class) {
if (instance == null) {
instance = new ImageLoader();
}
}
}
return instance;
}
/**
* 私有构造函数,保证单例模式
*
* @param context
*/
private ImageLoader() {
long maxMemory = Runtime.getRuntime().maxMemory();
long cacheSize = maxMemory / 8;
mMemoryCache = new LruCache<String, Bitmap>((int) cacheSize) {
protected int sizeOf(String key, Bitmap bitmap) {
return bitmap.getRowBytes() * bitmap.getHeight();
}
};
File f = new File(CACHE_PATH);
if (!f.exists()) {
f.mkdirs();
}
}
/**
* 存放图片信息
*/
class ImageRef {
/** 图片对应ImageView控件 */
ImageView imageView;
/** 图片URL地址 */
String url;
/** 图片缓存路径 */
String filePath;
/** 默认图资源ID */
int resId;
int width = 0;
int height = 0;
/**
* 构造函数
*
* @param imageView
* @param url
* @param resId
* @param filePath
*/
ImageRef(ImageView imageView, String url, String filePath, int resId) {
this.imageView = imageView;
this.url = url;
this.filePath = filePath;
this.resId = resId;
}
ImageRef(ImageView imageView, String url, String filePath, int resId,
int width, int height) {
this.imageView = imageView;
this.url = url;
this.filePath = filePath;
this.resId = resId;
this.width = width;
this.height = height;
}
}
/**
* 显示图片
*
* @param imageView
* @param url
* @param resId
*/
public void displayImage(ImageView imageView, String url, int resId) {
if (imageView == null) {
return;
}
// try {
// url = URLEncoder.encode(url,"utf-8").replaceAll("\\+", "%20");
// } catch (UnsupportedEncodingException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// url = Constants.IP_01 + "/" + url;
if (imageView.getTag() != null
&& imageView.getTag().toString().equals(url)) {
return;
}
if (resId >= 0) {
if (imageView.getBackground() == null) {
imageView.setBackgroundResource(resId);
}
imageView.setImageDrawable(null);
}
if (TextUtils.isEmpty(url)) {
return;
}
// 添加url tag
imageView.setTag(url);
// 读取map缓存
Bitmap bitmap = mMemoryCache.get(url);
if (bitmap != null) {
setImageBitmap(imageView, bitmap, false);
return;
}
// 生成文件名
String filePath = urlToFilePath(url);
if (filePath == null) {
return;
}
queueImage(new ImageRef(imageView, url, filePath, resId));
}
/**
* 显示图片固定大小图片的缩略图,一般用于显示列表的图片,可以大大减小内存使用
*
* @param imageView
* 加载图片的控件
* @param url
* 加载地址
* @param resId
* 默认图片
* @param width
* 指定宽度
* @param height
* 指定高度
*/
public void displayImage(ImageView imageView, String url, int resId,
int width, int height) {
if (imageView == null) {
return;
}
// url = Constants.IP_01 + "/" + url;
if (resId >= 0) {
if (imageView.getBackground() == null) {
imageView.setBackgroundResource(resId);
}
imageView.setImageDrawable(null);
}
if (TextUtils.isEmpty(url)) {
return;
}
// 添加url tag
imageView.setTag(url);
// 读取map缓存
Bitmap bitmap = null;
if (width > 0 && height > 0) {
bitmap = mMemoryCache.get(url+width+height);//
} else {
bitmap = mMemoryCache.get(url);
}
if (bitmap != null) {
setImageBitmap(imageView, bitmap, false);
return;
}
// 生成文件名
String filePath = urlToFilePath(url);
if (filePath == null) {
return;
}
queueImage(new ImageRef(imageView, url, filePath, resId, width, height));
}
/**
* 入队,后进先出
*
* @param imageRef
*/
public void queueImage(ImageRef imageRef) {
// 删除已有ImageView
Iterator<ImageRef> iterator = mImageQueue.iterator();
while (iterator.hasNext()) {
if (iterator.next().imageView == imageRef.imageView) {
iterator.remove();
}
}
// 添加请求
mImageQueue.push(imageRef);
sendRequest();
}
/**
* 发送请求
*/
private void sendRequest() {
// 开启图片加载线程
if (mImageLoaderHandler == null) {
HandlerThread imageLoader = new HandlerThread("image_loader");
imageLoader.start();
mImageLoaderHandler = new ImageLoaderHandler(
imageLoader.getLooper());
}
// 发送请求
if (mImageLoaderIdle && mImageQueue.size() > 0) {
ImageRef imageRef = mImageQueue.pop();
Message message = mImageLoaderHandler.obtainMessage(MSG_REQUEST,
imageRef);
mImageLoaderHandler.sendMessage(message);
mImageLoaderIdle = false;
mRequestQueue.add(imageRef);
}
}
/**
* 图片加载线程
*/
class ImageLoaderHandler extends Handler {
public ImageLoaderHandler(Looper looper) {
super(looper);
}
public void handleMessage(Message msg) {
if (msg == null)
return;
switch (msg.what) {
case MSG_REQUEST: // 收到请求
Bitmap bitmap = null;
Bitmap tBitmap = null;
if (msg.obj != null && msg.obj instanceof ImageRef) {
ImageRef imageRef = (ImageRef) msg.obj;
String url = imageRef.url;
if (url == null)
return;
bitmap = getBitmapFromSdcard(imageRef.filePath,
imageRef.width, imageRef.height);
if (bitmap != null) {
// ToolUtil.log("从disk缓存读取");
// 写入map缓存
if (imageRef.width > 0 && imageRef.height > 0) {
if (mMemoryCache.get(url + imageRef.width
+ imageRef.height) == null)
mMemoryCache.put(url + imageRef.width
+ imageRef.height, bitmap);
} else {
if (mMemoryCache.get(url) == null)
mMemoryCache.put(url, bitmap);
}
} else {
try {
byte[] data = loadByteArrayFromNetwork(url);
if (data != null) {
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inSampleSize = 1;
opt.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data, 0,
data.length, opt);
int bitmapSize = opt.outHeight * opt.outWidth
* 4;// pixels*3 if it's RGB and pixels*4
// if it's ARGB
if (bitmapSize > 1000 * 1200)
opt.inSampleSize = 2;
opt.inJustDecodeBounds = false;
tBitmap = BitmapFactory.decodeByteArray(data,
0, data.length, opt);
if (imageRef.width != 0 && imageRef.height != 0) {
bitmap = ThumbnailUtils
.extractThumbnail(
tBitmap,
imageRef.width,
imageRef.height,
ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
} else {
bitmap = tBitmap;
tBitmap = null;
}
if (bitmap != null && url != null) {
// 写入SD卡
if (imageRef.width > 0
&& imageRef.height > 0) {
writeBitmapToFile(bitmap,
imageRef.filePath
+ imageRef.width
+ imageRef.height);
mMemoryCache.put(url + imageRef.width
+ imageRef.height, bitmap);
} else {
writeBitmapToFile(bitmap,
imageRef.filePath);
mMemoryCache.put(url, bitmap);
}
isFromNet = true;
}
}
} catch (OutOfMemoryError e) {
}
}
}
if (mImageManagerHandler != null) {
Message message = mImageManagerHandler.obtainMessage(
MSG_REPLY, bitmap);
mImageManagerHandler.sendMessage(message);
}
break;
case MSG_STOP: // 收到终止指令
Looper.myLooper().quit();
break;
}
}
}
/** UI线程消息处理器 */
private Handler mImageManagerHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg != null) {
switch (msg.what) {
case MSG_REPLY: // 收到应答
do {
ImageRef imageRef = mRequestQueue.remove();
if (imageRef == null)
break;
if (imageRef.imageView == null
|| imageRef.imageView.getTag() == null
|| imageRef.url == null)
break;
if (!(msg.obj instanceof Bitmap) || msg.obj == null) {
break;
}
Bitmap bitmap = (Bitmap) msg.obj;
// 非同一ImageView
if (!(imageRef.url).equals((String) imageRef.imageView
.getTag())) {
break;
}
setImageBitmap(imageRef.imageView, bitmap, isFromNet);
isFromNet = false;
} while (false);
break;
}
}
// 设置闲置标志
mImageLoaderIdle = true;
// 若服务未关闭,则发送下一个请求。
if (mImageLoaderHandler != null) {
sendRequest();
}
}
};
/**
* 添加图片显示渐现动画
*
*/
private void setImageBitmap(ImageView imageView, Bitmap bitmap,
boolean isTran) {
if (isTran) {
final TransitionDrawable td = new TransitionDrawable(
new Drawable[] {
new ColorDrawable(android.R.color.transparent),
new BitmapDrawable(bitmap) });
td.setCrossFadeEnabled(true);
imageView.setImageDrawable(td);
td.startTransition(300);
} else {
imageView.setImageBitmap(bitmap);
}
}
/**
* 从网络获取图片字节数组
*
* @param url
* @return
*/
private byte[] loadByteArrayFromNetwork(String url) {
try {
// HttpGet method = new HttpGet(url);
// HttpResponse response = myapp.getHttpClient().execute(method);
// HttpEntity entity = response.getEntity();
// return EntityUtils.toByteArray(entity);
URL imageUrl = null;
InputStream is = null;
HttpURLConnection conn = null;
imageUrl = new URL(url);
conn = (HttpURLConnection) imageUrl.openConnection();
is = conn.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len = 0;
byte[] b = new byte[1024];
while ((len = is.read(b, 0, b.length)) != -1) {
baos.write(b, 0, len);
}
return baos.toByteArray();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
}
return null;
}
/**
* 根据url生成缓存文件完整路径名
*
* @param url
* @return
*/
public String urlToFilePath(String url) {
// 扩展名位置
int index = url.lastIndexOf('.');
if (index == -1) {
return null;
}
StringBuilder filePath = new StringBuilder();
// 图片存取路径
filePath.append(CACHE_PATH).append('/');
// 图片文件名
filePath.append(Md5Utils.md5(url));
return filePath.toString();
}
/**
* Activity#onStop后,ListView不会有残余请求。
*/
public void stop() {
// 清空请求队列
mImageQueue.clear();
}
private Bitmap getBitmapFromSdcard(String filePath, int width, int height) {
File f = null;
if (width > 0 && height > 0) {
f = new File(filePath + width + height);
} else {
f = new File(filePath);
}
if (f.exists()) {
return BitmapFactory.decodeFile(filePath);
}
return null;
}
private boolean writeBitmapToFile(Bitmap bitmap, String file) {
OutputStream out = null;
try {
out = new BufferedOutputStream(new FileOutputStream(file), 4096);
return bitmap.compress(CompressFormat.PNG, 100, out);
} catch (FileNotFoundException fe) {
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return false;
}
// public static void displayBigImage(ImageView imageView, String name,
// int defaultResId) {
// getInst().displayImage(imageView, Constant.IP + "/" + name,
// defaultResId);
// }
//
// public static void displaySmallImage(ImageView imageView, String name,
// int defaultResId) {
// getInst().displayImage(imageView, Constant.IP + "/" + name,
// defaultResId);
// }
}
调用方法
ImageLoader.getInst().displayImageimageview,
url, R.drawable.iv_basemap);
R.drawable.iv_basemap,这个是获取不到图片时候的默认图片