美文网首页
Android 四大引用的使用场景和区别

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

作者: 零心未 | 来源:发表于2018-06-08 14:27 被阅读0次
      注:本文只是用于自己学习记录,内容来自网络相关文章。
    
    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<Drawable> dsf = new SoftReference<Drawable>(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<ThisActivity> 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 四大引用的使用场景和区别

          本文链接:https://www.haomeiwen.com/subject/rpuosftx.html