public class BitmapManager {
private static HashMap<String, SoftReference<Bitmap>> cache;
private static ExecutorService pool;
private static Map<ImageView, String> imageViews;
private Bitmap defaultBmp;
static {
cache = new HashMap<String, SoftReference<Bitmap>>();
pool = Executors.newFixedThreadPool(5); //固定线程池
imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
}
public BitmapManager(){}
public BitmapManager(Bitmap def) {
this.defaultBmp = def;
}
/**
* 设置默认图片
* @param bmp
*/
public void setDefaultBmp(Bitmap bmp) {
defaultBmp = bmp;
}
/**
* 加载图片
* @param url
* @param imageView
*/
public void loadBitmap(String url, ImageView imageView) {
loadBitmap(url, imageView, this.defaultBmp, 0, 0);
}
/**
* 加载图片-可设置加载失败后显示的默认图片
* @param url
* @param imageView
* @param defaultBmp
*/
public void loadBitmap(String url, ImageView imageView, Bitmap defaultBmp) {
loadBitmap(url, imageView, defaultBmp, 0, 0);
}
/**
* 加载图片-可指定显示图片的高宽
* @param url
* @param imageView
* @param width
* @param height
*/
public void loadBitmap(String url, ImageView imageView, Bitmap defaultBmp, int width, int height) {
imageViews.put(imageView, url);
Bitmap bitmap = getBitmapFromCache(url);
if (bitmap != null) {
//显示缓存图片
imageView.setImageBitmap(bitmap);
} else {
//加载SD卡中的图片缓存
String filename = FileUtils.getFileName(url);
String filepath = imageView.getContext().getFilesDir() + File.separator + filename;
File file = new File(filepath);
if(file.exists()){
//显示SD卡中的图片缓存
Bitmap bmp = ImageUtils.getBitmap(imageView.getContext(), filename);
imageView.setImageBitmap(bmp);
}else{
//线程加载网络图片
imageView.setImageBitmap(defaultBmp);
queueJob(url, imageView, width, height);
}
}
}
/**
* 从缓存中获取图片
* @param url
*/
public Bitmap getBitmapFromCache(String url) {
Bitmap bitmap = null;
if (cache.containsKey(url)) { //判断该key里面有没有value
bitmap = cache.get(url).get();
}
return bitmap;
}
/**
* 从网络中加载图片
* @param url
* @param imageView
* @param width
* @param height
*/
public void queueJob(final String url, final ImageView imageView, final int width, final int height) {
/* Create handler in UI thread. */
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
String tag = imageViews.get(imageView);
if (tag != null && tag.equals(url)) {
if (msg.obj != null) {
imageView.setImageBitmap((Bitmap) msg.obj);
try {
//向SD卡中写入图片缓存
ImageUtils.saveImage(imageView.getContext(), FileUtils.getFileName(url), (Bitmap) msg.obj);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
};
pool.execute(new Runnable() {
public void run() {
Message message = Message.obtain();
message.obj = downloadBitmap(url, width, height);
handler.sendMessage(message);
}
});
}
/**
* 下载图片-可指定显示图片的高宽
* @param url
* @param width
* @param height
*/
private Bitmap downloadBitmap(String url, int width, int height) {
Bitmap bitmap = null;
try {
//http加载图片
bitmap = ApiClient.getNetBitmap(url);
if(width > 0 && height > 0) {
//指定显示图片的高宽
bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
}
//放入缓存
cache.put(url, new SoftReference<Bitmap>(bitmap));
} catch (AppException e) {
e.printStackTrace();
}
return bitmap;
}
}
代码就是这么多
1.静态代码块static{}的作用
程序一运行就运行的代码,不需要调用就可以自动执行。类被载入时,执行一次且仅一次。时机与静态变量一致
2.java的四种引用类型
在static{}里面有一个SoftReference。这个东西查阅资料后才知道叫做软引用,才知道java有四种引用类型,强引用,软引用,弱引用,虚引用
强引用:平时的引用方式都是强引用,特点是不会被回收掉,也就是不会被杀死,这样的优点是一直存在,但是过多的强引用导致了java对内存不能释放。
软引用(SoftReference):与强引用不同,可以被回收,当内存不够的时候就会被杀死。
弱引用(WeakReference): 与强引用正好相反,肯定被回收掉,当垃圾回收器扫描的时候,一旦发现就把他杀死。
由此可见,内存也是欺软怕硬的。
虚引用(PhantomReference):没看懂,我理解的大概意思就是不影响对象的生命周期,只不过在被杀死之前会出来做最后的动作。相当于一个标志。
3.java的内存回收机制
在看完引用类型之后会发现一个叫做垃圾回收器的东西。这个之前也没有听说过。查阅资料后,知道java提供了一个System.gc()的方法。这个方法是来告诉虚拟机要处理下内存,至于他何时处理,这就是他自己的问题了。那么何时虚拟机会处理内存中的垃圾呢?一般是,内存满了,这时候虚拟机会挂起所有线程,去检查下内存中的垃圾,把没用的清理掉,这时候软引用就会被杀死。不要显式的调用system.gc(),虽然他不一定能让虚拟机处理内存,但是他也增加了虚拟机处理内存的频率,这样对程序的运行显而易见是有危害的。所以为了避免内存溢出这种情况,要养成良好的编程习惯,不用的变量最后一定要赋值为0。
4.关于hashmap的一些知识
首先说下hashmap与hashtable,hashmap允许键值为空,table择不允许,所以当我们验证hashmap是否存在某个键的时候应该用containsKey()。
他们还有个区别就是hashtable则是线程安全的,它实现了方法的同步,可以直接用于多线程。hashmap则不是同步的,所以hashmap并不能直接用于多线程,需要手动同步,所以Collections提供了一个synchronizedMap方法实现方法的同步。
顺便说下,为何要实现方法的同步,假设多个线程使用同一个hashmap,不同步的话会导致多个线程同时修改hashmap的值,所以是不安全的。
5.缓存机制
缓存机制的意义:加快载入速度,毕竟从一个网站上下载一个图片等要比从本地上读取一个图片慢得多。同时也减少了流量的重复使用,降低成本。
缓存机制的实现:分为内存缓存与硬盘缓存
内存缓存就是将图片或者其他信息放入内存中,这样的优势是快,劣势是容易丢失 android提供了LruCache类,该代码中,是将图片以流的形式转换成bitmap,之后存入一个hashmap中
硬盘缓存就是将图片或者其他信息下载到本地,通过url(图片的标识码)查找图片以及实现图片的更新下载。