Android强引用、弱引用、软引用

2019-06-12  本文已影响0人  VitaAin
四种引用对比.png

一、强引用

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

特点:

java.lang.ref包中提供了几个类:SoftReference、WeakReference、PhantomReference,分别代表软引用、弱引用、虚引用。
ReferenceQueue类表示引用队列,它可以和这三种引用类联合使用,以便跟踪Java虚拟机回收所引用的对象的活动。


二、软引用(SoftReference)

软引用是除了强引用外,最强的引用类型。可以通过java.lang.ref.SoftReference使用软引用。

用法:

XXX xxx = new  XXX();
SoftReference ref = new SoftReference(xxx);
XXX anotherXXX = (XXX)ref.get();

如果一个对象持有软引用,那么如果内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。

软引用可用来实现内存敏感的高速缓存。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。ReferenceQueue中保存的对象是Reference对象,而且是已经失去了它所软引用的对象的Reference对象。

ReferenceQueue queue = new  ReferenceQueue();
SoftReference  ref = new  SoftReference(xxx, queue);

利用ReferenceQueue.poll()方法,可以检查哪个SoftReference所软引用的对象已经被回收。于是可以把这些失去软引用的对象的SoftReference对象清除掉。常用的方式为:

SoftReference ref = null;
while ((ref = (EmployeeRef) q.poll()) != null) {
  // 清除ref
}
示例
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
Drawable drawable = new BitmapDrawable(bitmap);
SoftReference<Drawable> drawableSoftReference = new SoftReference<Drawable>(drawable);
Drawable bgDrawable = drawableSoftReference.get();
if(bgDrawable!= null) {
  view.setBackground(bgDrawable);
}

通过软引用的get()方法,取得drawable对象实例的强引用,发现对象被未回收。在GC在内存充足的情况下,不会回收软引用对象。

在实际中,会一起从网络请求多个图片,这时就会请求非常多的内存空间,导致内存吃紧,系统开始GC。GC后,drawables.get()不再返回Drawable对象,而是返回null,这时屏幕上背景图不显示,在系统内存紧张的情况下,软引用被回收。

使用软引用以后,在OutOfMemory异常发生之前,这些缓存的图片资源的内存空间可以被释放掉的,从而避免内存达到上限,避免Crash发生。

注意

在垃圾回收器对Java对象回收前,SoftReference类所提供的get方法会返回Java对象的强引用,一旦垃圾线程回收该Java对象之后,get方法将返回null。所以在获取软引用对象的代码中,一定要判断是否为null,以免出现NullPointerException导致应用崩溃。


三、弱引用(WeakReference)

用法:

WeakReference<XXX> sr = new WeakReference<XXX>(new XXX());

如果一个对象持有弱引用,那么在垃圾回收器线程扫描的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。

弱引用也可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

弱引用与软引用的根本区别:

只具有弱引用的对象拥有更短暂的生命周期,可能随时被回收;
而只具有软引用的对象只有当内存不够的时候才被回收,在内存足够的时候,通常不被回收。

使用场景:

Handler中的使用,防止内存泄露。

软引用、弱引用都非常适合来保存那些可有可无的缓存数据。如果这样做,当系统内存不足时,这些缓存数据会被回收,不会导致内存溢出。而当内存资源充足时,这些缓存数据又可以存在相当长的时间。

如何选择软引用、弱引用?


四、虚引用(PhantomReference)

虚引用是所有引用类型中最弱的一个。

一个持有虚引用的对象,和没有引用几乎是一样的,随时都可能被垃圾回收器回收。当试图通过虚引用的get()方法取得强引用时,总是会失败。并且,虚引用必须和引用队列一起使用,它的作用在于跟踪垃圾回收过程。

当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在垃圾回收后,销毁这个对象,将这个虚引用加入引用队列。

上一篇 下一篇

猜你喜欢

热点阅读