/**
* Created by Administrator on 2017/6/5 0005.
*/
public class MyImageLoader {
/**
* 如果我们需要加载一个音乐的专辑图片,
* 可以先从内存缓存中去进行该专辑
* 图片的查找,如果内存缓存中没有的话,
* 再从文件缓存中查找,如果文件缓存中也
* 没有的话,说明我们还从来没有网络上加载
* 过要使用的图片,这时我们再从网络上加载
* 加载完成之再分别把这个图片缓存到内存和
* 文件中,以便于下次再使用的时候,可以直接
* 从缓存中拿到。
*/
//强引用里的数据是永远不可能被垃圾回收器回收的
//软引用里存的数据在android3.0之后就变的不可靠。
/*LruCache 集合最近最少使用
存在于该集合中的数据都是强引用
我们可以在定义这样的集合时设置一个最大的
存储空间,当空间满了要加新的数据时会根据最近
最少使用的算法
*/
public static LruCache<String, Bitmap> lruCacheMemory = null;
static {
int maxSize = (int) Runtime.getRuntime().maxMemory();
lruCacheMemory = new LruCache<String, Bitmap>(maxSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getHeight() * value.getRowBytes();
}
};
}
/**
* @param context
* @param imageView 专辑图片控件
* @param imageUrl 网络图片的路径
*/
public static void setBitmapFromCache(Context context, ImageView imageView, String imageUrl) {
//从缓存中获得的图片
Bitmap bitmap = null;
//判断如果没有提供图片的路径就直接返回
if (TextUtils.isEmpty(imageUrl)) {
return;
}
//先从内存中查找有没有要使用的图片
//如果有直接使用
bitmap = getBitmapFromMemory(imageUrl);
if (bitmap != null) {
//把图片应用到控件上
imageView.setImageBitmap(bitmap);
return;
}
//再从文件缓存中查找有没有要使用的图片
//如果有就直接使用
bitmap = getBitmapFromFile(context, imageUrl);
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
return;
}
//说明使用的图片还没有从网加载过,
//从网络上加载该图片
loadBitmapFromHttp(context, imageView, imageUrl);
}
private static void loadBitmapFromHttp(Context context, ImageView imageView, String imageUrl) {
//要访问网络,实现异步加载
ImageAsyncTask task = new ImageAsyncTask(context, imageView);
//启动异步任务
task.execute(imageUrl);
}
//实现异步图片加载的任务类
private static class ImageAsyncTask extends AsyncTask<String, Void, Bitmap> {
private Context context;
private ImageView imageView;
static int imageWidth;
static int imageHeight;
ImageAsyncTask(Context context,
ImageView imageView) {
this.context = context;
this.imageView = imageView;
ViewGroup.LayoutParams layoutParams = imageView.getLayoutParams();
imageWidth = layoutParams.width;
imageHeight = layoutParams.height;
}
@Override
protected Bitmap doInBackground(
String... strings) {
String path = strings[0];
Bitmap bitmap = null;
//构建URL对象
try {
URL url = new URL(path);
HttpURLConnection connection =
(HttpURLConnection)
url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
connection.setDoInput(true);
connection.connect();
int statusCode = connection.getResponseCode();
if (statusCode == 200) {
//获得响应的结果
InputStream is = connection.getInputStream();
//bitmap = BitmapFactory.decodeStream(is);
bitmap = compressBitmap(is, imageWidth, imageHeight);
//判断该图片是否加载成功
if (bitmap != null) {
//将图片缓存到内存中
lruCacheMemory.put(path, bitmap);
//将图片缓存到文件中
saveBitmapToFile(context, path, bitmap);
return bitmap;
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
//把图片应用到控件上
imageView.setImageBitmap(bitmap);
}
}
/**
* 压缩图片
* @param is
* @param imageWidth 原始图片宽度
* @param imageHeight 原始图片高度
* @return
*/
private static Bitmap compressBitmap(InputStream is, int imageWidth, int imageHeight) {
Bitmap bitmap;
byte[] datas = getBitmapByteArray(is);
BitmapFactory.Options options = new BitmapFactory.Options();
//为true时。只获取尺寸,不获取别的
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(datas, 0, datas.length, options);
//获得原始图片的边界的宽度和高度
int outWidth = options.outWidth;
int outHeight = options.outHeight;
//设置压缩后的宽度和高度,即目标宽高
int targetWidth = imageWidth;
int targetHeight = imageHeight;
//计算宽度方向上的压缩比例
int scaleWidth = outWidth / targetWidth;
//计算高度方向上的压缩比例
int scaleHeight = outHeight / targetHeight;
//最终的比例,拿最大的
int scaleFinal = scaleWidth > scaleHeight ? scaleWidth : scaleHeight;
//特殊情况处理,万一原始图片比目标宽高要小!
if (scaleFinal <= 0) {
scaleFinal = 1;
}
options.inSampleSize = scaleFinal;
options.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeByteArray(datas, 0, datas.length, options);
return bitmap;
}
/**
* 将输入流转换成字节数组,以供BitmapFactory获取图片的尺寸等信息
*
* @param is
* @return
*/
public static byte[] getBitmapByteArray(InputStream is) {
ByteArrayOutputStream os = null;
byte[] datas = null;
try {
os = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
os.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
os.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
datas = os.toByteArray();
return datas;
}
//将图片缓存到文件中
private static void saveBitmapToFile(Context context, String path, Bitmap bitmap) {
File cacheDir = context.getCacheDir();
if (!cacheDir.exists()) {
cacheDir.mkdir();
}
//获得要缓存的文件的名字
String fileName = path.substring(path.lastIndexOf("/") + 1);
//创建一个文件对象
File file =
new File(cacheDir, fileName);
try {
OutputStream os =
new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private static Bitmap getBitmapFromFile(Context context, String imageUrl) {
String fileName = imageUrl.substring(imageUrl.lastIndexOf("/") + 1);
File cachDir = context.getCacheDir();
if (cachDir != null) {
for (File file : cachDir.listFiles()) {
if (fileName.equals(file.getName())) {
//查找到了要使用的图了
return BitmapFactory.decodeFile(file.getAbsolutePath());
}
}
}
return null;
}
private static Bitmap getBitmapFromMemory(String imageUrl) {
Bitmap bitmap = null;
bitmap = lruCacheMemory.get(imageUrl);
return bitmap;
}
}