/**
* @Title: BitmapCache.java
*/
package com.zero.imagedispose;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.Hashtable;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
/**
* @ClassName: BitmapCache
* @Description: 图片处理,防止溢出
* @author ZeRo_Ci
* @date 2014-3-26 下午2:52:05
*
*/
public class BitmapCache {
private static BitmapCache cache;
/** 用于内同存储 */
private Hashtable<String, BitmapRef> bitmapRefs;
/** 垃圾Reference的队列(所引用的对象已经被回收,则将该引用存入队列中 */
private ReferenceQueue<Bitmap> q;
/**
*
* @ClassName: BitmapRef
* @Description: 继承SoftReference,使得每个实例都具有可识别的标识
* @author ZeRo_Ci
* @date 2014-3-26 下午3:13:39
*
*/
class BitmapRef extends SoftReference<Bitmap> {
private String _key = "";
public BitmapRef(Bitmap r, ReferenceQueue<Bitmap> q, String key) {
super(r, q);
_key = key;
}
}
public BitmapCache() {
bitmapRefs = new Hashtable<String, BitmapCache.BitmapRef>();
q = new ReferenceQueue<Bitmap>();
}
/**
* 取得缓存器实例
*/
protected static BitmapCache getInstance() {
if (cache == null) {
cache = new BitmapCache();
}
return cache;
}
/**
* 依据所指定的文件名获取图片
*/
protected Bitmap getBitmap(String filename, AssetManager assetManager) {
Bitmap bitmapImage = null;
// 缓存中是否有该Bitmap实例的软引用,如果有,从软引用中取得。
if (bitmapRefs.containsKey(filename)) {
BitmapRef ref = bitmapRefs.get(filename);
bitmapImage = ref.get();
}
// 如果没有软引用,或者从软引用中得到的实例是null,重新构建一个实例,
// 并保存对这个新建实例的软引用
if (bitmapImage == null) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inTempStorage = new byte[16 * 1024];
}
BufferedInputStream stream;
try {
/**
* BufferedInputStream与BufferedOutputStream的使用
*
* 1. java.io.BufferedInputStream与java.io.BufferedOutputStream可以为
* InputStream,OutputStream类增加缓冲区功能。构建BufferedInputStream实例时,
* 需要给定一个InputStream类型的实例
* ,实现BufferedInputStream时,实际上最后是实现InputStream实例
* 。同样,构建BufferedOutputStream时
* ,也需要给定一个OutputStream实例,实现BufferedOutputStream时
* ,实际上最后是实现OutputStream实例。
*
* 2. BufferedInputStream的数据成员buf是一个位数组,默认为2048字节
* 。当读取数据来源时,例如文件,BufferedInputStream会尽量将buf填满
* 。当使用read()方法时,实际上是先读取buf中的数据,而不是直接对数据来源作读取。当buf中的数据不足时,
* BufferedInputStream才会再实现给定的InputStream对象的read()方法,从指定的装置中提取数据。
*
* 3. BufferedOutputStream的数据成员buf也是一个位数组,默认为512字节。当使用write()
* 方法写入数据时实际上会先将数据写到buf中
* ,当buf已满时才会实现给定的OutputStream对象的write()方法,将buf数据写到目的地
* ,而不是每次都对目的地作写入的动作
*/
stream = new BufferedInputStream(assetManager.open(filename));
bitmapImage = BitmapFactory.decodeStream(stream);
this.addCacheBitmap(bitmapImage, filename);
} catch (IOException e) {
e.printStackTrace();
}
return bitmapImage;
}
/**
* 以软引用的方式对一个Bitmap对象的实例进行引用并保存该引用
*/
private void addCacheBitmap(Bitmap bitmap, String key) {
cleanCache();
BitmapRef ref = new BitmapRef(bitmap, q, key);
bitmapRefs.put(key, ref);
}
/**
* 清理缓存
*/
private void cleanCache() {
BitmapRef ref = null;
while ((ref = (BitmapRef) q.poll()) != null) {
bitmapRefs.remove(ref._key);
}
}
/**
* 清除Cache中的全部内容
*/
private void clearCache() {
cleanCache();
bitmapRefs.clear();
System.gc();
System.runFinalization();
}
}
/**
* @Title: ImageLoaderTask.java
*/
package com.zero.imagedispose;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import com.zero.uitls.TaskParam;
import android.app.ActionBar.LayoutParams;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.widget.ImageView;
/**
* @ClassName: ImageLoaderTask
* @Description: 图片加载
* @author ZeRo_Ci
* @date 2014-3-26 下午2:52:23
*
*/
// AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(
// 以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.
public class ImageLoaderTask extends AsyncTask<TaskParam, Void, Bitmap> {
private TaskParam taskParam;
/** 防止溢出 */
private final WeakReference<ImageView> reference;
public ImageLoaderTask(ImageView imageView) {
reference = new WeakReference<ImageView>(imageView);
}
/**
* 参考文献:
*
* http://blog.163.com/gobby_1110/blog/static/29281715201352004329356/
* http://www.2cto.com/kf/201203/122729.html
* http://blog.csdn.net/cjjky/article/details/6684959
*
* AsyncTask源码地址 :
* https://github.com/android/platform_frameworks_base/blob/master
* /core/java/android/os/AsyncTask.java
*/
protected Bitmap doInBackground(TaskParam... params) {
taskParam = params[0];
return loadImageFile(taskParam.getFilename(),
taskParam.getAssetManager());
}
/**
* 加载图片文件
*/
private Bitmap loadImageFile(final String filename,
final AssetManager manager) {
InputStream inputStream = null;
try {
Bitmap bitmap = BitmapCache.getInstance().getBitmap(filename,
taskParam.getAssetManager());
return bitmap;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/*
* (non-Javadoc)
*
* @see android.os.AsyncTask#onPostExecute(java.lang.Object)
*/
@Override
protected void onPostExecute(Bitmap result) {
if (isCancelled()) {
result = null;
}
if (reference != null) {
ImageView imageView = reference.get();
if (imageView != null) {
if (result != null) {
int width = result.getWidth();
int height = result.getHeight();
LayoutParams layoutParams = (LayoutParams) imageView
.getLayoutParams();
/** 调整高度 */
layoutParams.height = (height * taskParam.getItemWidth())
/ width;
imageView.setLayoutParams(layoutParams);
imageView.setImageBitmap(result);
}
}
}
}
}
安卓开发、ios开发、QT移动开发技术交流学习群 347131054 。欢迎有志做移动开发的同行加入!