防内存不足的HashMap类

众所周知,在移动端进行开发,最麻烦的就是内存不足的情况,当内存不足时,会关闭某些应用,对应用的使用造成影响。比如,要保存每个运行的View,记录到栈中,方便进行回退操作时,一般都是使用Stack或Map进行保存。</span>

一般都是如下写法:
</pre><p><pre name="code" class="html"> /**
	 * 用于保存加载过的中间界面的对象(用于下次再次加载时使用,不需要重新实例化一个View)
	 */
	private Map<String, BaseUI> VIEWCACHE = new HashMap<String, BaseUI>();// K
	if (VIEWCACHE.containsKey(key)) {
		// 在容器中存在该类(则说明已经加载了该类)
		targetUI = VIEWCACHE.get(key);
			// Log.w(TAG, "已经加载了该类, 则直接使用");
	} else {
		AbLog.i(TAG, "第一次加载");
		// 自己手动生成View
	try {
			Constructor<? extends BaseUI> constructor = targetClazz
					.getConstructor(Context.class);
			targetUI = constructor.newInstance(getContext());
			VIEWCACHE.put(key, targetUI);
		} catch (Exception e) {
		e.printStackTrace();
		}


	}



但当内存不足时,整个应用都会因为这个Map而崩溃。为了防止这种情况,可以通过软引用的方式,包装占用内存的对象,降低他的优先级,使其能够被GC回收。而包装后的Map对象如下:

/**
 * 软引用的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;
		}

	}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值