package com.panpass.main;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
/*
* 图片管理
* 异步获取图片,直接调用loadImage()函数,该函数自己判断是从缓存还是网络加载
* 同步获取图片,直接调用getBitmap()函数,该函数自己判断是从缓存还是网络加载
* 仅从本地获取图片,调用getBitmapFromNative()
* 仅从网络加载图片,调用getBitmapFromHttp()
*
*/
public class ImageManager {
public static ImageManager im = null;
private final static String TAG = "ImageManager";
private ImageMemoryCache imageMemoryCache; // 内存缓存
private ImageFileCache imageFileCache; // 文件缓存
// 正在下载的image列表
public static HashMap<String, Handler> ongoingTaskMap = new HashMap<String, Handler>();
// 等待下载的image列表
public static HashMap<String, Handler> waitingTaskMap = new HashMap<String, Handler>();
// 同时下载图片的线程个数
final static int MAX_DOWNLOAD_IMAGE_THREAD = 4;
private final Handler downloadStatusHandler = new Handler() {
public void handleMessage(Message msg) {
startDownloadNext();
}
};
public static ImageManager getInstance(Context mContext) {
if (im == null) {
synchronized (ImageManager.class) {
if (im == null) {
im = new ImageManager(mContext);
}
}
}
return im;
}
public ImageManager(Context mContext) {
imageMemoryCache = new ImageMemoryCache();
imageFileCache = new ImageFileCache(mContext);
}
/**
* 获取图片,多线程的入口
*/
public void loadBitmap(String urlStr, Handler handler) {
String url = urlStr.hashCode() + "";
// 先从内存缓存中获取,取到直接加载
Bitmap bitmap = getBitmapFromNative(urlStr);
if (bitmap != null) {
Message msg = Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("url", url);
msg.obj = bitmap;
msg.setData(bundle);
handler.sendMessage(msg);
} else {
downloadBmpOnNewThread(urlStr, handler);
}
}
/**
* 新起线程下载图片
*/
private void downloadBmpOnNewThread(final String urlStr,
final Handler handler) {
final String url = urlStr.hashCode() + "";
if (ongoingTaskMap.size() >= MAX_DOWNLOAD_IMAGE_THREAD) {
synchronized (waitingTaskMap) {
waitingTaskMap.put(url, handler);
}
} else {
synchronized (ongoingTaskMap) {
ongoingTaskMap.put(url, handler);
}
new Thread() {
public void run() {
Bitmap bmp = getBitmapFromHttp(urlStr);
// 不论下载是否成功,都从下载队列中移除,再由业务逻辑判断是否重新下载
// 下载图片使用了httpClientRequest,本身已经带了重连机制
synchronized (ongoingTaskMap) {
ongoingTaskMap.remove(url);
}
if (downloadStatusHandler != null) {
downloadStatusHandler.sendEmptyMessage(0);
}
Message msg = Message.obtain();
msg.obj = bmp;
Bundle bundle = new Bundle();
bundle.putString("url", url);
msg.setData(bundle);
if (handler != null) {
handler.sendMessage(msg);
}
}
}.start();
}
}
/**
* 依次从内存,缓存文件,网络上加载单个bitmap,不考虑线程的问题
*/
public Bitmap getBitmap(String urlStr) {
String url = urlStr.hashCode() + "";
// 从内存缓存中获取图片
Bitmap bitmap = imageMemoryCache.getBitmapFromMemory(url);
if (bitmap == null) {
// 文件缓存中获取
bitmap = imageFileCache.getImageFromFile(url);
if (bitmap != null) {
// 添加到内存缓存
imageMemoryCache.addBitmapToMemory(url, bitmap);
} else {
// 从网络获取
bitmap = getBitmapFromHttp(urlStr);
}
}
return bitmap;
}
/**
* 从内存或者缓存文件中获取bitmap
*/
public Bitmap getBitmapFromNative(String urlStr) {
String url = urlStr.hashCode() + "";
Bitmap bitmap = null;
bitmap = imageMemoryCache.getBitmapFromMemory(url);
if (bitmap == null) {
bitmap = imageFileCache.getImageFromFile(url);
if (bitmap != null) {
// 添加到内存缓存
imageMemoryCache.addBitmapToMemory(url, bitmap);
}
}
return bitmap;
}
/**
* 通过网络下载图片,与线程无关
*/
public Bitmap getBitmapFromHttp(String urlStr) {
String url = urlStr.hashCode() + "";
Bitmap bmp = null;
try {
byte[] tmpPicByte = getImageBytes(urlStr);
if (tmpPicByte != null) {
bmp = BitmapFactory.decodeByteArray(tmpPicByte, 0,
tmpPicByte.length);
}
tmpPicByte = null;
} catch (Exception e) {
e.printStackTrace();
}
if (bmp != null) {
// 添加到文件缓存
imageFileCache.saveBitmapToFile(bmp, url);
// 添加到内存缓存
imageMemoryCache.addBitmapToMemory(url, bmp);
}
return bmp;
}
/**
* 下载链接的图片资源
*
* @param url
*
* @return 图片
*/
public byte[] getImageBytes(String urlStr) {
if (urlStr != null && !"".equals(urlStr)) {
HttpGet get = new HttpGet(urlStr);
get.addHeader("Accept-Encoding", "indentity");
HttpClient client = new DefaultHttpClient();
HttpResponse response = null;
try {
response = client.execute(get);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
InputStream is = response.getEntity().getContent();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len = -1;
while ((len = is.read(buf)) != -1) {
baos.write(buf, 0, len);
}
return baos.toByteArray();
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 取出等待队列第一个任务,开始下载
*/
private void startDownloadNext() {
synchronized (waitingTaskMap) {
Iterator<Entry<String, Handler>> iter = waitingTaskMap.entrySet()
.iterator();
if (iter.hasNext()) {
Map.Entry<String, Handler> entry = (Map.Entry<String, Handler>) iter
.next();
if (entry != null) {
waitingTaskMap.remove(entry.getKey());
downloadBmpOnNewThread((String) entry.getKey(),
(Handler) entry.getValue());
}
}
}
}
/**
* 图片变为圆角
*
* @param bitmap
* :传入的bitmap
* @param pixels
* :圆角的度数,值越大,圆角越大
* @return bitmap:加入圆角的bitmap
*/
public static Bitmap toRoundCorner(Bitmap bitmap, int pixels) {
if (bitmap == null)
return null;
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = pixels;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
// paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
}
package com.panpass.main;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
public class ImageFileCache {
<span style="white-space:pre"> </span>private File cacheDir;
<span style="white-space:pre"> </span>public ImageFileCache(Context context) {
<span style="white-space:pre"> </span>// 如果有SD卡则在SD卡中建一个LazyList的目录存放缓存的图片
<span style="white-space:pre"> </span>// 没有SD卡就放在系统的缓存目录中
<span style="white-space:pre"> </span>if (android.os.Environment.getExternalStorageState().equals(
<span style="white-space:pre"> </span>android.os.Environment.MEDIA_MOUNTED))
<span style="white-space:pre"> </span>cacheDir = new File(
<span style="white-space:pre"> </span>android.os.Environment.getExternalStorageDirectory(),
<span style="white-space:pre"> </span>"LazyList");
<span style="white-space:pre"> </span>else
<span style="white-space:pre"> </span>cacheDir = context.getCacheDir();
<span style="white-space:pre"> </span>if (!cacheDir.exists())
<span style="white-space:pre"> </span>cacheDir.mkdirs();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>public Bitmap getImageFromFile(String url) {
<span style="white-space:pre"> </span>// 将url的hashCode作为缓存的文件名
<span style="white-space:pre"> </span>// Another possible solution
<span style="white-space:pre"> </span>// String filename = URLEncoder.encode(url);
<span style="white-space:pre"> </span>File f = new File(cacheDir, url);
<span style="white-space:pre"> </span>if(f.exists()){
<span style="white-space:pre"> </span>return BitmapFactory.decodeFile(f.getAbsolutePath());
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>return null;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>public void saveBitmapToFile(Bitmap bm ,String url) {
<span style="white-space:pre"> </span>File file=new File(cacheDir,url);//将要保存图片的路径
<span style="white-space:pre"> </span>try {
<span style="white-space:pre"> </span>BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
<span style="white-space:pre"> </span>bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);
<span style="white-space:pre"> </span>bos.flush();
<span style="white-space:pre"> </span>bos.close();
<span style="white-space:pre"> </span>} catch (IOException e) {
<span style="white-space:pre"> </span>e.printStackTrace();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>public void clear() {
<span style="white-space:pre"> </span>File[] files = cacheDir.listFiles();
<span style="white-space:pre"> </span>if (files == null)
<span style="white-space:pre"> </span>return;
<span style="white-space:pre"> </span>for (File f : files)
<span style="white-space:pre"> </span>f.delete();
<span style="white-space:pre"> </span>}
}
package com.panpass.main;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import android.graphics.Bitmap;
import android.util.Log;
public class ImageMemoryCache {
<span style="white-space:pre"> </span>private static final String TAG = "MemoryCache";
<span style="white-space:pre"> </span>/**
<span style="white-space:pre"> </span> * 放入缓存时是个同步操作 LinkedHashMap构造方法的最后一个参数true代表这个map里的元素将按照最 近使用次数由少到多排列,
<span style="white-space:pre"> </span> * 即LRU。
<span style="white-space:pre"> </span> * 这样的好处是如果要将缓存中的元素替换,则先遍历出最近最少使用的元素来替换以提高效率
<span style="white-space:pre"> </span> */
<span style="white-space:pre"> </span>private Map<String, Bitmap> cache = Collections
<span style="white-space:pre"> </span>.synchronizedMap(new LinkedHashMap<String, Bitmap>(10, 1.5f, true));
<span style="white-space:pre"> </span>// 缓存中图片所占用的字节,初始0,将通过此变量严格控制缓存所占用的堆内存
<span style="white-space:pre"> </span>private long size = 0;// current allocated size
<span style="white-space:pre"> </span>// 缓存只能占用的最大堆内存
<span style="white-space:pre"> </span>private long limit = 1000000;// max memory in bytes
<span style="white-space:pre"> </span>public ImageMemoryCache() {
<span style="white-space:pre"> </span>// use 25% of available heap size
<span style="white-space:pre"> </span>setLimit(Runtime.getRuntime().maxMemory() / 4);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>public void setLimit(long new_limit) {
<span style="white-space:pre"> </span>limit = new_limit;
<span style="white-space:pre"> </span>Log.i(TAG, "MemoryCache will use up to " + limit / 1024. / 1024. + "MB");
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>public Bitmap getBitmapFromMemory(String id) {
<span style="white-space:pre"> </span>try {
<span style="white-space:pre"> </span>if (!cache.containsKey(id))
<span style="white-space:pre"> </span>return null;
<span style="white-space:pre"> </span>return cache.get(id);
<span style="white-space:pre"> </span>} catch (NullPointerException ex) {
<span style="white-space:pre"> </span>return null;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>public void addBitmapToMemory(String id, Bitmap bitmap) {
<span style="white-space:pre"> </span>try {
<span style="white-space:pre"> </span>if (cache.containsKey(id))
<span style="white-space:pre"> </span>size -= getSizeInBytes(cache.get(id));
<span style="white-space:pre"> </span>cache.put(id, bitmap);
<span style="white-space:pre"> </span>size += getSizeInBytes(bitmap);
<span style="white-space:pre"> </span>checkSize();
<span style="white-space:pre"> </span>} catch (Throwable th) {
<span style="white-space:pre"> </span>th.printStackTrace();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>/**
<span style="white-space:pre"> </span> * 严格控制堆内存,如果超过将首先替换最近最少使用的那个图片缓存
<span style="white-space:pre"> </span> *
<span style="white-space:pre"> </span> */
<span style="white-space:pre"> </span>private void checkSize() {
<span style="white-space:pre"> </span>Log.i(TAG, "cache size=" + size + " length=" + cache.size());
<span style="white-space:pre"> </span>if (size > limit) {
<span style="white-space:pre"> </span>// 先遍历最近最少使用的元素
<span style="white-space:pre"> </span>Iterator<Entry<String, Bitmap>> iter = cache.entrySet().iterator();
<span style="white-space:pre"> </span>while (iter.hasNext()) {
<span style="white-space:pre"> </span>Entry<String, Bitmap> entry = iter.next();
<span style="white-space:pre"> </span>size -= getSizeInBytes(entry.getValue());
<span style="white-space:pre"> </span>iter.remove();
<span style="white-space:pre"> </span>if (size <= limit)
<span style="white-space:pre"> </span>break;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>Log.i(TAG, "Clean cache. New size " + cache.size());
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>public void clear() {
<span style="white-space:pre"> </span>cache.clear();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>/**
<span style="white-space:pre"> </span> * 图片占用的内存
<span style="white-space:pre"> </span> *
<span style="white-space:pre"> </span> * @param bitmap
<span style="white-space:pre"> </span> * @return
<span style="white-space:pre"> </span> */
<span style="white-space:pre"> </span>long getSizeInBytes(Bitmap bitmap) {
<span style="white-space:pre"> </span>if (bitmap == null)
<span style="white-space:pre"> </span>return 0;
<span style="white-space:pre"> </span>return bitmap.getRowBytes() * bitmap.getHeight();
<span style="white-space:pre"> </span>}
}
package com.panpass.main;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Window;
import android.widget.ImageView;
import com.example.imgdemo.R;
public class MainActivity extends Activity {
<span style="white-space:pre"> </span>private Context mContext = this;
<span style="white-space:pre"> </span>private ImageView img1,img2,img3,img4,img5;
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>protected void onCreate(Bundle savedInstanceState) {
<span style="white-space:pre"> </span>super.onCreate(savedInstanceState);
<span style="white-space:pre"> </span>getWindow().requestFeature(Window.FEATURE_NO_TITLE);
<span style="white-space:pre"> </span>setContentView(R.layout.main_acticity);
<span style="white-space:pre"> </span>img1 = (ImageView) findViewById(R.id.img1);
<span style="white-space:pre"> </span>img2 = (ImageView) findViewById(R.id.img2);
<span style="white-space:pre"> </span>img3 = (ImageView) findViewById(R.id.img3);
<span style="white-space:pre"> </span>img4 = (ImageView) findViewById(R.id.img4);
<span style="white-space:pre"> </span>img5 = (ImageView) findViewById(R.id.img5);
<span style="white-space:pre"> </span>ImageManager.getInstance(mContext).loadBitmap("https://www.baidu.com/img/baidu_jgylogo3.gif?v=26599715.gif", new Handler(){
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public void handleMessage(Message msg) {
<span style="white-space:pre"> </span>super.handleMessage(msg);
<span style="white-space:pre"> </span>img1.setImageBitmap((Bitmap)msg.obj);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>});
<span style="white-space:pre"> </span>ImageManager.getInstance(mContext).loadBitmap("https://www.baidu.com/img/baidu_jgylogo3.gif?v=26599715.gif", new Handler(){
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public void handleMessage(Message msg) {
<span style="white-space:pre"> </span>super.handleMessage(msg);
<span style="white-space:pre"> </span>img2.setImageBitmap((Bitmap)msg.obj);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>});
<span style="white-space:pre"> </span>ImageManager.getInstance(mContext).loadBitmap("https://www.baidu.com/img/baidu_jgylogo3.gif?v=26599715.gif", new Handler(){
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public void handleMessage(Message msg) {
<span style="white-space:pre"> </span>super.handleMessage(msg);
<span style="white-space:pre"> </span>img3.setImageBitmap((Bitmap)msg.obj);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>});
<span style="white-space:pre"> </span>ImageManager.getInstance(mContext).loadBitmap("https://www.baidu.com/img/baidu_jgylogo3.gif?v=26599715.gif", new Handler(){
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public void handleMessage(Message msg) {
<span style="white-space:pre"> </span>super.handleMessage(msg);
<span style="white-space:pre"> </span>img4.setImageBitmap((Bitmap)msg.obj);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>});
<span style="white-space:pre"> </span>ImageManager.getInstance(mContext).loadBitmap("https://www.baidu.com/img/baidu_jgylogo3.gif?v=26599715.gif", new Handler(){
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public void handleMessage(Message msg) {
<span style="white-space:pre"> </span>super.handleMessage(msg);
<span style="white-space:pre"> </span>img5.setImageBitmap((Bitmap)msg.obj);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>});
<span style="white-space:pre"> </span>//<span style="white-space:pre"> </span>img2.setImageBitmap(ImageManager.getInstance(mContext).getBitmap("https://www.baidu.com/img/baidu_jgylogo3.gif?v=26599715.gif"));
<span style="white-space:pre"> </span>//
<span style="white-space:pre"> </span>//<span style="white-space:pre"> </span>img3.setImageBitmap(ImageManager.getInstance(mContext).getBitmap("https://www.baidu.com/img/baidu_jgylogo3.gif?v=26599715.gif"));
<span style="white-space:pre"> </span>//<span style="white-space:pre"> </span>img4.setImageBitmap(ImageManager.getInstance(mContext).getBitmap("https://www.baidu.com/img/baidu_jgylogo3.gif?v=26599715.gif"));
<span style="white-space:pre"> </span>//<span style="white-space:pre"> </span>img5.setImageBitmap(ImageManager.getInstance(mContext).getBitmap("https://www.baidu.com/img/baidu_jgylogo3.gif?v=26599715.gif"));
<span style="white-space:pre"> </span>}
}