Android 四大引用的使用场景和区别

  注:本文只是用于自己学习记录,内容来自网络相关文章。
image.png

在Android java.lang.ref包中包含SoftReference类、WeakReference类、PhantomReference类、ReferenceQueue类和Reference抽象类。

1、强引用
直接new出的对象:String str = new String("ABC");
1.1、强引用介绍
普遍使用的引用对象,但是即便内存不足时也不会通过回收机制来回收而导致程序奔溃
1.2、强引用的特点
强引用可以直接访问目标对象
强引用所指的对象在任何时候都不会被回收,即便jvm抛出oom
强引用可能会导致内存泄漏

2、软引用
SoftReference:软引用–>当虚拟机内存不足时,将会回收它指向的对象;需要获取对象时,可以调用get方法。
软引用对象不会很快被jvm回收,jvm 会根据当前堆的使用情况来判断何时回收,当堆的使用频率接近阀值时才会被回收

    2.1、软引用的使用场景
    例如从网络上获取图片,然后将获取的图片显示的同时,通过软引用缓存起来。当下次再去网络上获取图片时,首先会检查要获取的图片缓存中是否存在,若存在,直接取出来,不需要再去网络上获取。

    2.2、基本用法
    MySoftReference msf = new MySoftReference();
    SoftReference sf = new SoftReference(msf);
    MySoftReference mySoftReference =(MySoftReference) sf.get();

    2.3、软引用的基本特点
        2.3.1、描述
               如果内存足够,软引用是不会被jvm回收的;
               如果内存不够,会根据堆栈的使用情况来回收引用;
               未被回收的软引用是一直可被程序占有的;

                软引用可以和引用队列(ReferenceQueue)联合使用来实现内存紧张的高速缓存,      
                如果软引用引用的对象被回收,Java虚拟机会把改软引用对象加到与之关联的引用      
                队列中。eg:
               ReferenceQueue rq = new ReferenceQueue();
               SoftReference sf = new SoftReference(msf,rf);

               当软引用对象被回收后,ReferenceQueue队列中存储着强引用的Reference,然后可通过poll()来判断当前引用队列是否有失去软引用的对象,如果队列为空,将返回一个null,否则该方法返回队列中前面的一个Reference对象。可以检测出哪个软引用对象被回收,然后将其清除。eg:
              Reference reference =null;
              while((reference==(EmployeeRef)rq.poll())){
                      //清除操作
                      reference =null;
                       System.gc();
                  }
  
          2.3.2、使用场景
               图片占用内存过大
                View view = findViewById(***);
                Bitmap bitmap = 
                BitmapFactory.decodeResource(getResource(),R.mipmap.ic_launcher);
                Drawable drawable = new BitmapDrawable(bitmap);
                SoftReference dsf = new SoftReference(drawable);
                if(dsf!=null){
                      view.setImageResource(dsf.get())
                  }
        
              解释:在使用软引用时直接通过get()获取到图片对象,当加载大量图片时,内存紧 
              张,软引用会被回收get()获取到的图片对象为null,(所以在使用软引用对象时一定 
              要判断非null,以免出现空指针异常)图片不显示。

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


 3、弱引用

     3.1、介绍:
    WeakReference: 弱引用–>随时可能会被垃圾回收器回收,不一定要等到虚拟机内存不足 
    时才强制回收。要获取对象时,同样可以调用get方法。

     3.2、特点:
      如果当前引用只具备弱引用,那么在垃圾回收时,不管内存是否够用都会被回收,但垃圾回 
    收机制优先级低,一般不会被很快发现弱引用对象。

     3.3、使用场景
      避免内存泄漏  handler
      这种情况就是由于android的特殊机制造成的:当一个android主线程被创建的时候,同时会 
   有一个Looper对象被创建,而这个Looper对象会实现一个MessageQueue(消息队列),当我 
   们创建一个handler对象时,而handler的作用就是放入和取出消息从这个消息队列中,每当 
   我们通过handler将一个msg放入消息队列时,这个msg就会持有一个handler对象的引用。

  因此当Activity被结束后,这个msg在被取出来之前,这msg会继续存活,但是这个msg仍持有handler的引用,而handler在Activity中创建,会持有Activity的引用,因而当Activity结束后,Activity对象并不能够被gc回收,因而出现内存泄漏。
  activity结束后,referenceQueue并不会结束,若这个队列中存在消息对象msg,而msg还持有handler引用,但activity已结束消息msg不能被处理,从而导致永久持有handler对象,而handler又依赖activity,所以发生内存泄漏。
  java中所有非静态的对象都会持有当前类的强引用,而静态对象则只会持有当前类的弱引用。声明为静态后,handler将会持有一个Activity的弱引用,而弱引用会很容易被gc回收,这样就能解决Activity结束后,gc却无法回收的情况。eg:
  MyHandler myHandler = new MyHandler(this);
  public static class MyHandler extends Handler{
  WeakReference ref;
  MyHandler(ThisActivity activity){
  ref = new WeakReference<>(activity);
   }
}

4、虚引用 PhantomReference
虚引用是所有引用类型中最弱的一个。一个持有虚引用的对象,和没有引用几乎是一样的,随时都可能被垃圾回收器回收。当试图通过虚引用的get()方法取得强引用时,总是会失败。并且,虚引用必须和引用队列一起使用,它的作用在于跟踪垃圾回收过程。 当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在垃圾回收后,销毁这个对象,奖这个虚引用加入引用队列。Android实际开发中不用。

5、四种引用的区别

  5.1 弱引用和软引用区别
    弱引用与软引用的根本区别在于:只具有弱引用的对象拥有更短暂的生命周期,可能随时被回收。而只具有软引用的对象只有当内存不够的时候才被回收,在内存足够的时候,通常不被回收。

 5.2 使用软引用或者弱引用防止内存泄漏
   在Android应用的开发中,为了防止内存溢出,在处理一些占用内存大而且声明周期较长的对象时候,可以尽量应用软引用和弱引用技术。
   软引用,弱引用都非常适合来保存那些可有可无的缓存数据。如果这样做,当系统内存不足时,这些缓存数据会被回收,不会导致内存溢出。而当内存资源充足时,这些缓存数据又可以存在相当长的时间。

 5.3 到底什么时候使用软引用,什么时候使用弱引用呢?
   个人认为,如果只是想避免OutOfMemory异常的发生,则可以使用软引用。如果对于应用的性能更在意,想尽快回收一些占用内存比较大的对象,则可以使用弱引用。
   还有就是可以根据对象是否经常使用来判断。如果该对象可能会经常使用的,就尽量用软引用。如果该对象不被使用的可能性更大些,就可以用弱引用。
   另外,和弱引用功能类似的是WeakHashMap。WeakHashMap对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的回收,回收以后,其条目从映射中有效地移除。WeakHashMap使用ReferenceQueue实现的这种机制。
image.png

·

你可能感兴趣的:(Android 四大引用的使用场景和区别)