构建高速缓存

时间:2023-02-13 07:38:35

当缓存过多时,会造成内存不足,此时应用容易崩溃。

解决办法:

①低内存预警:

Intent.ACTION_DEVICE_STORAGE_LOW;
设备内存不足时发出的广播,此广播只能由系统使用,其它APP不可用
Intent.ACTION_DEVICE_STORAGE_OK;
设备内存从不足到充足时发出的广播,此广播只能由系统使用,其它APP不可用

②构建高速缓存:

降低BaseUI的引用级别

⑴强引用(StrongReference)
    强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。

⑵软引用(SoftReference)
    如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。
软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。


软引用例子:

/**
* 软引用的map集合
*
* @author Administrator
*
* @param <K>
* @param <V>
*/
public class SoftMap<K, V> extends HashMap<K, V> {
// 降低对象的引用界别——V

private HashMap<K, SoftValue<K, V>> temp;// 存放袋子的集合
private ReferenceQueue<V> queue;

public SoftMap() {
// Object v=new Object();//占用内存较多
// SoftReference sr=new SoftReference(v);//v的引用级别被降低了

// 第一步:将占用内存较多的手机,添加到袋子中
// 第二步:手机被GC回收,清理空袋子

temp = new HashMap<K, SoftValue<K, V>>();
queue = new ReferenceQueue<V>();// 但凡装V的袋子,都可以放到该集合中
}

@Override
public V put(K key, V value) {
// SoftReference<V> sr = new SoftReference<V>(value);// 将手机装到袋子中
// SoftReference(T referent, ReferenceQueue<? super T> q)

// 记录回收掉的袋子引用ReferenceQueue
SoftValue<K, V> sr = new SoftValue<K, V>(key, value, queue);
temp.put(key, sr);
return null;
}

@Override
public V get(Object key) {
clearsr();
SoftValue<K, V> sr = temp.get(key);
if (sr != null) {
// 垃圾回收器清除,则此方法将返回 null。
return sr.get();
}

return null;
}

@Override
public boolean containsKey(Object key) {
// 什么叫真正的contain
// temp.containsKey(key);
/*
* if(get(key)!=null) { return true; }else{ return false; }
*/
return get(key) != null;
}

/**
* 清理空袋子
*/
private void clearsr() {
// 方式一:循环temp,逐一判断是否有手机,存在问题:如果当前内存够用,循环无用
// 方式二:GC知道把那个袋子的手机给回收了,利用GC,让其记录曾经被偷的手机(存入到集合中)
// 如果能够控制该集合,再循环该集合,里面存放的一定被回收了
// 轮询此队列,查看是否存在可用的引用对象。
// 如果存在一个立即可用的对象,则从该队列中"移除"此对象并返回。
// 否则此方法立即返回 null。
SoftValue<K, V> poll = (SoftValue<K, V>) queue.poll();
while (poll != null) {
temp.remove(poll.key);
poll = (SoftValue<K, V>) queue.poll();
}
}

/**
* 增强版的袋子,增加了key,方便清理操作
*
* @author Administrator
*
* @param <K>
* @param <V>
*/
private class SoftValue<K, V> extends SoftReference<V> {
private Object key;

public SoftValue(K key, V r, ReferenceQueue<? super V> q) {
super(r, q);
this.key = key;
}

}
}

软引用的应用:

// 利用手机内存空间,换应用应用的运行速度
private static Map<String, BaseUI> VIEWCACHE;// K
// :唯一的标示BaseUI的子类

static {
// 16M,如果不足<16M(模拟器)
// 32M,真机
// 判断内存是否充足
if (MemoryManager.hasAcailMemory()) {
VIEWCACHE = new HashMap<String, BaseUI>();
} else {
VIEWCACHE = new SoftMap<String, BaseUI>();
}
}

另外还需要在返回键时做处理:

BaseUI targetUI = VIEWCACHE.get(key);
if (targetUI != null) {
currentUI.onPause();
middle.removeAllViews();
middle.addView(targetUI.getChild());
targetUI.onResume();
currentUI = targetUI;

changeTitleAndBottom();
}else{
// 处理方式一:创建一个新的目标界面:存在问题——如果有其他的界面传递给被删除的界面
// 处理方式二:寻找一个不需要其他界面传递数据——跳转到首页
changeUI(Hall.class);
PromptManager.showToast(getContext(), "应用在低内存下运行");
}