package com.qianfeng.assistant.modules.other.utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.widget.ImageView;
import com.qianfeng.assistant.R;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
*
* 图片加载类
*
* Created by Liu Jianping
*
* @date : 15/12/9.
*/
public class ImageLoader {
private MemoryCache memoryCache = new MemoryCache();
private FileCache fileCache;
private Map<ImageView, String> p_w_picpathViews = Collections
.synchronizedMap(new WeakHashMap<ImageView, String>());
// 线程池
private ExecutorService executorService;
// 默认图片
private final int defaultDrawable = R.drawable.ic_pull_logo;
private final int strokeWidth = 0;
private boolean isCircle;
private static ImageLoader instance;
//是否压缩图片
private boolean compress;
private ImageLoader(Context context) {
fileCache = new FileCache(context);
executorService = Executors.newFixedThreadPool(10);
}
/**
* 获取ImageLoader单例
*
* @param context
* @return
*/
public static ImageLoader getInstance(Context context) {
if (instance == null) {
synchronized (ImageLoader.class) {
if (instance == null) {
instance = new ImageLoader(context);
}
}
}
return instance;
}
/**
* 显示图片
*
* @param url
* @param p_w_picpathView
* @param circle
* 是否显示圆形图片
*/
public void displayImage(String url, ImageView p_w_picpathView, boolean circle) {
isCircle = circle;
p_w_picpathViews.put(p_w_picpathView, url);
// 先从内存缓存中查找
Bitmap bitmap = memoryCache.get(url);
if (bitmap != null) {
p_w_picpathView.setImageBitmap(bitmap);
} else {
p_w_picpathView.setImageResource(defaultDrawable);
// 若没有的话则开启新线程加载图片
loadBitmapFromNet(url, p_w_picpathView);
}
}
/**
* 清除缓存
*/
public void clearCache() {
memoryCache.clear();
fileCache.clear();
}
/**
* 防止图片错位
*
* @param holder
* @return false表示错位
*/
private boolean p_w_picpathViewReused(BitmapHolder holder) {
String tag = p_w_picpathViews.get(holder.p_w_picpathView);
return tag == null || !tag.equals(holder.url);
}
/**
* 下载图片操作
*
* @param is
* @param os
*/
private void copyStream(InputStream is, OutputStream os) {
final int buffer_size = 1024;
try {
byte[] bytes = new byte[buffer_size];
while (true) {
int count = is.read(bytes, 0, buffer_size);
if (count == -1) {
break;
}
os.write(bytes, 0, count);
}
} catch (Exception e) {
LogUtils.e("ImageLoader", "ImageLoader 保存文件失败...");
// e.printStackTrace();
}
}
/**
* 加载网络图片
*
* @param url
* @param p_w_picpathView
*/
private void loadBitmapFromNet(String url, ImageView p_w_picpathView) {
BitmapHolder p = new BitmapHolder(url, p_w_picpathView);
executorService.submit(new BitmapLoader(p));
}
/**
* 获取图片 先从缓存中去查找,如果没有再从网络下载
*
* @param url
* 图片地址
* @return
*/
public Bitmap getBitmap(String url) {
File f = fileCache.getFile(url);
// 先从文件缓存中查找是否有
Bitmap b = decodeFile(f);
if (b != null) {
return b;
}
// 最后从指定的url中下载图片
try {
Bitmap bitmap = null;
URL p_w_picpathUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) p_w_picpathUrl
.openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
conn.setInstanceFollowRedirects(true);
InputStream is = conn.getInputStream();
OutputStream os = new FileOutputStream(f);
copyStream(is, os);
os.close();
bitmap = decodeFile(f);
return bitmap;
} catch (Exception e) {
// e.printStackTrace();
LogUtils.d("ImageLoader", "下载失败");
return null;
}
}
/**
* 压缩图片
*
* @param f
* 图片的本地路径
* @return
*/
private Bitmap decodeFile(File f) {
try {
Bitmap bitmap = null;
if (compress) {
// 不加载图片的情况下获得图片的宽高
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f), null, o);
final int REQUIRED_SIZE = 70;
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
// 如果长或宽大于70,那么把图片的高宽缩小一半
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE
|| height_tmp / 2 < REQUIRED_SIZE) {
break;
}
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
// 把图片的高宽缩小一半
bitmap = BitmapFactory.decodeStream(new FileInputStream(f),
null, o2);
} else {
BitmapFactory.Options o = new BitmapFactory.Options();
bitmap = BitmapFactory.decodeStream(new FileInputStream(f),
null, o);
}
return isCircle ? createCircleBitmap(bitmap) : bitmap;
} catch (FileNotFoundException e) {
LogUtils.e("ImageLoader", e.getMessage());
// e.printStackTrace();
}
return null;
}
/**
* 设置是否压缩图片
*
* @param isCompress
*/
public void setCompress(boolean isCompress) {
compress = isCompress;
}
/**
* 用来封装Url和ImageView,防止图片错位里用
*/
private class BitmapHolder {
public String url;
public ImageView p_w_picpathView;
public BitmapHolder(String u, ImageView i) {
url = u;
p_w_picpathView = i;
}
}
/**
* 图片下载器
*/
private class BitmapLoader implements Runnable {
BitmapHolder holder;
BitmapLoader(BitmapHolder photoToLoad) {
this.holder = photoToLoad;
}
@Override
public void run() {
// 如果没有错位那么不做任何处理,如果错位那么需要再做一次加载处理
if (p_w_picpathViewReused(holder)) {
return;
}
Bitmap bmp = getBitmap(holder.url);
memoryCache.put(holder.url, bmp);
if (p_w_picpathViewReused(holder)) {
return;
}
BitmapDisplayer displayer = new BitmapDisplayer(bmp, holder);
// 更新的操作放在UI线程中
holder.p_w_picpathView.post(displayer);
}
}
/**
* 图片显示器
*/
private class BitmapDisplayer implements Runnable {
Bitmap bitmap;
BitmapHolder holder;
public BitmapDisplayer(Bitmap b, BitmapHolder bh) {
bitmap = b;
holder = bh;
}
public void run() {
if (p_w_picpathViewReused(holder)) {
return;
}
if (bitmap != null) {
holder.p_w_picpathView.setImageBitmap(bitmap);
} else {
holder.p_w_picpathView.setImageResource(defaultDrawable);
}
}
}
/**
* 把 源圆片 加工成 圆形图片
*
* @param resource
* 源圆片
* @return
*/
public Bitmap createCircleBitmap(Bitmap resource) {
int width = resource.getWidth();
Paint paint = new Paint();
// 画圆或者弧形图,需要抗锯齿
paint.setAntiAlias(true);
// 创建一张空图片, 这张图片只有宽高,没有内容
Bitmap target = Bitmap.createBitmap(width, width,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(target);
// 画一个和原图片宽高一样的内切圆
canvas.drawCircle(width / 2, width / 2, (width - strokeWidth) / 2,
paint);
// 取两图的交集(也就是重合的部分)
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
// 把源图覆盖上去
canvas.drawBitmap(resource, 0, 0, paint);
return target;
}
}
转载于:https://blog.51cto.com/tiantiankaixin/1869420