package l.test1.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
/**
* Bitmap工具类,缓存用过的指定数量的图片,使用此工具类,不再需要手动管理Bitmap内存 原理:
* 用一个队列保存使用Bitmap的顺序,每次使用Bitmap将对象移动到队列头 当内存不够,或者达到制定的缓存数量的时候,回收队列尾部图片
* 保证当前使用最多的图片得到最长时间的缓存,提高速度
*
* @author liaoxingliao
*
*/
public final class BitMapUtil {
private static final Size ZERO_SIZE = new Size(0, 0);
private static final Options OPTIONS_GET_SIZE = new Options();
private static final Options OPTIONS_DECODE = new Options();
private static final byte[] LOCKED = new byte[0];
private static final LinkedList<String> CACHE_ENTRIES = new LinkedList<String>(); // 此对象用来保持Bitmap的回收顺序,保证最后使用的图片被回收
private static final Queue<QueueEntry> TASK_QUEUE = new LinkedList<QueueEntry>(); // 线程请求创建图片的队列
private static final Set<String> TASK_QUEUE_INDEX = new HashSet<String>(); // 保存队列中正在处理的图片的key,有效防止重复添加到请求创建队列
private static final Map<String, Bitmap> IMG_CACHE_INDEX = new HashMap<String, Bitmap>(); // 缓存Bitmap
// 通过图片路径,图片大小
private static int CACHE_SIZE = 200; // 缓存图片数量
static {
OPTIONS_GET_SIZE.inJustDecodeBounds = true;
// 初始化创建图片线程,并等待处理
new Thread() {
{
setDaemon(true);
}
public void run() {
while (true) {
synchronized (TASK_QUEUE) {
if (TASK_QUEUE.isEmpty()) {
try {
TASK_QUEUE.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
QueueEntry entry = TASK_QUEUE.poll();
String key = createKey(entry.path, entry.width,
entry.height);
TASK_QUEUE_INDEX.remove(key);
createBitmap(entry.path, entry.width, entry.height);
}
}
}.start();
}
/**
* 创建一张图片 如果缓存中已经存在,则返回缓存中的图,否则创建一个新的对象,并加入缓存
* 宽度,高度,为了缩放原图减少内存的,如果输入的宽,高,比原图大,返回原图
*
* @param path 图片物理路径 (必须是本地路径,不能是网络路径)
* @param width 需要的宽度
* @param height 需要的高度
* @return
*/
public static Bitmap getBitmap(String path, int width, int height) {
Bitmap bitMap = null;
try {
if (CACHE_ENTRIES.size() >= CACHE_SIZE) {
destoryLast();
}
bitMap = useBitmap(path, width, height);
if (bitMap != null && !bitMap.isRecycled()) {
return bitMap;
}
bitMap = createBitmap(path, width, height);
String key = createKey(path, width, height);
synchronized (LOCKED) {
IMG_CACHE_INDEX.put(key, bitMap);
CACHE_ENTRIES.addFirst(key);
}
} catch (OutOfMemoryError err) {
destoryLast();
System.out.println(CACHE_SIZE);
return createBitmap(path, width, height);
}
return bitMap;
}
/**
* 设置缓存图片数量 如果输入负数,会产生异常
*
* @param size
*/
public static void setCacheSize(int size) {
if (size <= 0) {
throw new RuntimeException("size :" + size);
}
while (size < CACHE_ENTRIES.size()) {
destoryLast();
}
CACHE_SIZE = size;
}
/**
* 加入一个图片处理请求到图片创建队列
*
* @param path
* 图片路径(本地)
* @param width
* 图片宽度
* @param height
* 图片高度
*/
public static void addTask(String path, int width, int height) {
QueueEntry entry = new QueueEntry();
entry.path = path;
entry.width = width;
entry.height = height;
synchronized (TASK_QUEUE) {
String key = createKey(path, width, height);
if (!TASK_QUEUE_INDEX.contains(key)
&& !IMG_CACHE_INDEX.containsKey(key)) {
TASK_QUEUE.add(entry);
TASK_QUEUE_INDEX.add(key);
TASK_QUEUE.notify();
}
}
}
/**
* 通过图片路径返回图片实际大小
* @param path 图片物理路径
* @return
*/
public static Size getBitMapSize(String path) {
File file = new File(path);
if (file.exists()) {
InputStream in = null;
try {
in = new FileInputStream(file);
BitmapFactory.decodeStream(in, null, OPTIONS_GET_SIZE);
return new Size(OPTIONS_GET_SIZE.outWidth,
OPTIONS_GET_SIZE.outHeight);
} catch (FileNotFoundException e) {
return ZERO_SIZE;
} finally {
closeInputStream(in);
}
}
return ZERO_SIZE;
}
// ------------------------------------------------------------------ private Methods
// 将图片加入队列头
private static Bitmap useBitmap(String path, int width, int height) {
Bitmap bitMap = null;
String key = createKey(path, width, height);
synchronized (LOCKED) {
bitMap = IMG_CACHE_INDEX.get(key);
if (null != bitMap) {
if (CACHE_ENTRIES.remove(key)) {
CACHE_ENTRIES.addFirst(key);
}
}
}
return bitMap;
}
// 回收最后一张图片
private static void destoryLast() {
synchronized (LOCKED) {
String key = CACHE_ENTRIES.removeLast();
if (key.length() > 0) {
Bitmap bitMap = IMG_CACHE_INDEX.remove(key);
if (bitMap != null && !bitMap.isRecycled()) {
bitMap.recycle();
bitMap = null;
}
}
}
}
// 创建键
private static String createKey(String path, int width, int height) {
if (null == path || path.length() == 0) {
return "";
}
return path + "_" + width + "_" + height;
}
// 通过图片路径,宽度高度创建一个Bitmap对象
private static Bitmap createBitmap(String path, int width, int height) {
File file = new File(path);
if (file.exists()) {
InputStream in = null;
try {
in = new FileInputStream(file);
Size size = getBitMapSize(path);
if (size.equals(ZERO_SIZE)) {
return null;
}
int scale = 1;
int a = size.getWidth() / width;
int b = size.getHeight() / height;
scale = Math.max(a, b);
synchronized (OPTIONS_DECODE) {
OPTIONS_DECODE.inSampleSize = scale;
Bitmap bitMap = BitmapFactory.decodeStream(in, null,
OPTIONS_DECODE);
return bitMap;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
closeInputStream(in);
}
}
return null;
}
// 关闭输入流
private static void closeInputStream(InputStream in) {
if (null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 图片大小
static class Size {
private int width, height;
Size(int width, int height) {
this.width = width;
this.height = height;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
}
// 队列缓存参数对象
static class QueueEntry {
public String path;
public int width;
public int height;
}
}
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
test.rar (70个子文件)
test
.project 807B
project.properties 360B
proguard.cfg 1KB
src
l
test1
ListAdapter.java 3KB
util
BitMapUtil.java 7KB
TestActivity.java 4KB
ViewEntry.java 1KB
queue
PhotoDownLoadCallBack.java 143B
PhotoDownLoadQueue.java 3KB
PhotoSearchCallBack.java 109B
PhotoSearchQueue.java 2KB
AndroidManifest.xml 847B
res
drawable-ldpi
icon.png 2KB
drawable-hdpi
icon.png 4KB
drawable
color.xml 120B
drawable-mdpi
icon.png 3KB
layout
lstviewlayout.xml 740B
main.xml 785B
values
strings.xml 106B
assets
gen
l
test1
R.java 909B
default.properties 362B
.classpath 281B
bin
resources.ap_ 12KB
l
test1
R$layout.class 398B
R$drawable.class 396B
R$attr.class 307B
TestActivity$4.class 2KB
TestActivity.class 4KB
ViewEntry.class 1KB
TestActivity$2.class 864B
TestActivity$3.class 1KB
util
BitmapUtil.class 3KB
Size.class 527B
R$id.class 441B
ListAdapter.class 6KB
R.class 454B
R$string.class 365B
ListAdapter$ViewHolder.class 1KB
TestActivity$1.class 1KB
queue
PhotoDownLoadQueue.class 5KB
PhotoDownLoadCallBack.class 215B
PhotoSearchCallBack.class 175B
PhotoSearchQueue.class 2KB
classes
l
test1
R$layout.class 398B
R$drawable.class 396B
R$attr.class 307B
TestActivity.class 4KB
ViewEntry.class 1KB
TestActivity$2.class 864B
TestActivity$3.class 1KB
util
BitMapUtil$QueueEntry.class 449B
BitMapUtil$Size.class 616B
BitMapUtil$1.class 1KB
BitMapUtil.class 6KB
R$id.class 441B
ListAdapter.class 4KB
R.class 454B
R$string.class 365B
ListAdapter$ViewHolder.class 1KB
TestActivity$1.class 1KB
queue
PhotoDownLoadQueue.class 5KB
PhotoSearchQueue$1.class 900B
PhotoDownLoadCallBack.class 215B
PhotoSearchCallBack.class 198B
PhotoSearchQueue.class 3KB
test.apk 24KB
res
drawable-ldpi
icon.png 2KB
drawable-hdpi
icon.png 4KB
drawable-mdpi
icon.png 2KB
classes.dex 20KB
共 70 条
- 1
liaoxingliao
- 粉丝: 15
- 资源: 4
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
- 3
- 4
- 5
- 6
前往页