强引用实例自然不会被GC回收!
如何引出弱引用?弱引用的实际用途是什么?
什么是内存泄漏?Java使用有向图机制,通过GC自动检查内存中的对象;如果GC发现一个或一组对象为不可达的状态,则将该对象从内存中回收。也就是说:一个对象不被任何引用所指向,则该对象会在被GC发现的时候回收。
可能导致内存泄漏的实例:
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
mImageView.setImageBitmap(mBitmap);
};
};
当使用内部类(或者匿名类)来创建Handler的时候,Handler对象会隐式地持有一个外部类的对象(通常是Activity)的引用(否则怎么可能通过Handler来操作Activity的View?)。而Handler通常会伴随着一个耗时的后台线程(比如:拉取网络图片);该后台线程在任务执行完毕后,通过消息机制通知Handler,然后Handler把图片更新到界面上。假设用户在网络请求过程中关闭了Activity,正常情况下这个Activity不再被使用,就有可能被GC回收;但此时线程尚未执行完毕,而该线程持有Handler的引用(不然怎么发送消息给Handler?),Handler又持有Activity的引用,就导致该Activity无法被回收(内存泄漏),直到网络请求结束(如:图片下载完毕)。另外如果执行了Handler的postDelayed(),该方法会将Handler装入一个Message,并把该Message推到MessageQueue中,由此产生了一条链式结构:MessageQueue->Message->Handler->Activity,导致Activity被持有引用而无法被回收。(总结:实例对象被其他对象持有引用,而无法被回收)
内存泄漏的危害是什么?内存泄漏会引发虚拟机占用内存过高。对于Android应用程序来说,用户打开一个Activity,使用完之后关闭,内存泄漏;执行上述步骤多次,程序占用内存超过系统限制。
如何避免内存泄漏?可以使用什么方法?由此引出了弱引用。
用于非必需对象,被弱引用关联的对象只能生存到下一次GC发生之前。当GC工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。
/**
* <功能描述> 用于加载Bitmap实例
*
* @author Administrator
*/
public class AsyncDrawable extends BitmapDrawable {
private final WeakReference
public AsyncDrawable(Resources res, Bitmap bitmap,
BitmapWorkerTask bitmapWorkerTask) {
super(res, bitmap);
// bitmapWorkerTaskReference实例关联BitmapWorkerTask
bitmapWorkerTaskReference = new WeakReference
bitmapWorkerTask);
}
public BitmapWorkerTask getBitmapWorkerTask() {
return bitmapWorkerTaskReference.get();
}
}
此时 WeakReference
好处在于:可以申请任意多个 bitmapWorkerTask 实例对象,并与弱引用对象关联;使用前,先判断是否已被释放;如果已被释放,则重新申请;若未被释放,则直接使用。WeakReference负责了释放规则。
使用了上述代码后,用户在关闭Activity之后,就算后台线程还没有结束,但由于仅有一个来自Handler的弱引用指向Activity,所有GC仍然会在检查的时候把Activity回收掉。