Android學習筆記之SoftReference軟引用...


PS:其實這一篇和上一篇很類似,都是為了解決內存不足(OOM)這種情況的發生...

 

學習內容:

1.對象的引用類....

  最近也是通過項目中知道了一些東西,涉及到了對象的引用類,對象的引用類分為多種,強引用(其實就是正常的引用),使用SoftReference實現軟引用,Weak Reference(弱引用) PhantomRefrence(虛引用)...這三個引用類我只詳細的介紹一下SoftReference實現軟引用...其他的就一筆帶過....

強引用:

Object darker=new Object();
Object darker_1=darker;
darker=null;
darker_1=null;

  強引用其實相對而言就非常的簡單,也就是我們一般實例化對象后,對對象的一個引用就屬於強引用,並且只要這個引用存在,那么GC(垃圾回收器)也就絕對不會去回收當前被引用的對象...如果將這個對象的引用設置為null,那么就代表GC可以對這個對象進行回收了...

軟引用:

  軟引用是我要細說的一個部分,先說一下軟引用的一個引用目的,軟引用的使用是與內存掛鈎的一個引用類,主要應用於內存敏感的高速緩存,其實在Android中是經常使用的到的,由於Android的虛擬機是基於寄存器的Dalvik,它的堆大小只有16M,我們都清楚無論是Android應用程序,還是Java引用程序,在實例化對象的時候都是在堆中完成的...因此在Android中這個堆的大小要求確實是很苛刻的,一旦我們讀取的資源數據過大,或者是內存里的對象由於聲明的周期太長,沒有被及時的釋放,那么就很有可能造成OOM的發生...我們都知道GC的回收機制在正常的情況下並不是時時刻刻都在工作的,它的工作時間是不定期的,因此如果在GC不工作的期間我們的內存已經爆表,那就必定導致程序終止...OOM在Android是經常見到的一種情況,對象的不及時釋放,static關鍵字的使用,線程不可控,還有最常見的就是在讀取Bitmap的時候導致這種情況的發生...

  那么OOM是一個非常嚴重的問題,但是如果內存得不到充分的使用,這個其實也是一個潛在的問題,SoftReference(軟引用),其實給我的感覺就是為了解決這樣的問題,每一個對象通過軟引用進行實例化,那么這個對象的數據也就會被保存起來,當需要再次調用這個對象中的數據的時候,只需要通過對象的get()方法就可以獲取到該對象所保存的數據信息,其實也會是我們所說的cache,當內存快要不足的時候,GC會迅速的把所有的軟引用清除掉,釋放內存空間...這樣不僅結合了對象的cache,同時還解決了OOM的發生,一舉兩得...雖然說是一舉兩得的東西,保證了內存能夠安全的被使用,那么相反就要犧牲效率,在每一個軟引用對象被實例化的時候,其實還是需要耗費許多的時間的...因此到底如何運用,取決於我們遇到的問題.

  簡單的來一段小代碼...

Object obj=new Object();
SoftRefenrence sc = new SoftReference(obj);//這里使用了軟引用...

/*
 *在這個期間,有可能會出現內存不足的情況發生,那么GC就會直接把所有的軟引用全部清除..並釋放內存空間
 *如果內存空間足夠的話,那么就GC就不會進行工作...
 *GC的工作取決於內存的大小,以及其內部的算法,,,,
 */
   
if(sr!=null){
        //如果軟引用還存在,那么直接就可以獲取這個對象的相關數據...這樣就實現了cache...
        obj = sr.get();

    }else{
        //如果已經不存在,表示GC已經將其回收,我們需要重新實例化對象,獲取數據信息...
          
        obj = new Object();
        sr = new SoftReference(obj);
}

  很簡單的一段代碼,沒什么實際的意義,只是為了方便理解...在Android中,其實有一些時候還是由於Bitmap的問題導致內存不足的發生,圖片相對而言還是比較大的,像素高的圖片在讀取的情況下是非常耗費內存的,如果讀取的圖片過多的話,那就更加的顯而易見了,圖片過多,內存會被吃的非常的緊,因此我們需要在Bitmap中去使用軟引用,這樣就可以避免OOM的發生...還可以有效的去使用內存...

  還是簡單的說一下其中的道理,比如說我們讀取到了一張圖片,這張圖片被讀取后就以cache的形式保存起來...當我們的應用程序如果還是需要這張圖片的資源數據的話,那么直接通過軟引用中的get()方法,就可以得到圖片中的資源數據,..這樣就沒必要再次進行讀取了,直接從cache中就可以讀取得到,如果圖片過多,保存的對象也會越來越多,那么當內存將要發生OOM的時候,GC會迅速把所有的軟引用,也就是這些對象的引用和內控件迅速釋放...防止OOM的發生...下面貼一段小小的代碼...

import java.lang.ref.SoftReference;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import android.graphics.Bitmap;

public class MemoryCache {

    //將HashMap封裝成一個線程安全的集合,並且使用軟引用的方式防止OOM(內存不足)...
    //由於在ListView中會加載大量的圖片.那么為了有效的防止OOM導致程序終止的情況...
    private Map<String,SoftReference<Bitmap>>cache=Collections.synchronizedMap(new HashMap<String, SoftReference<Bitmap>>());
    
    public Bitmap get(String id){
        if(!cache.containsKey(id))        
            return null;    
        SoftReference<Bitmap>ref=cache.get(id);
        return ref.get();
        
    }
    
    public void put(String id,Bitmap bitmap){
        cache.put(id, new SoftReference<Bitmap>(bitmap));
    }
    
    public void clear(){
        cache.clear();
    }
}

  這段代碼也非常的簡單...就是定義了一個集合,將Bitmap的軟引用保存在集合當中,如果圖片資源存在於集合內部,那么直接就進行取出操作即可...如果存儲的容量過大..超出了內存的限制..那么直接調用clear函數將其清空...這段代碼隸屬於一個項目中的小模塊....

 

  最后簡單的說一下弱引用...

  弱引用:

  弱引用其實和軟引用差不太多,不過是使用WeakReference去實例化一個對象,並且GC是不會根據內存的原因去指定時間去回收對象...弱引用可以在未被GC回收之前的任意時間段,都能獲取到這個對象的相關信息...一旦GC將其回收,那么就獲取不到這個對象的相關數據了...該回收的時候,GC會自動的將其進行回收,不會根據內存的大小而決定時候去釋放這個對象所占用的內存...簡單的舉個例子...

Object obj = Object A();

    WeakReference wr = new WeakReference(obj);

    obj = null;

    //在這個時間段....短時間內GC不會被啟動...那么我們就可以再次獲取到這個對象保存的數據信息...
    //在這個期間如果GC啟動了回收,那么就無法獲取到這個對象所包含的數據信息了...

  if (wr.get()==null) {

  System.out.println("obj 已經被清除了 ");

  } else {

  System.out.println("obj 尚未被清除,其信息是 "+obj.toString());

  }

}

  總之軟引用的使用是為了解決OOM的狀況發生...避免OOM的發生不僅僅只使用SoftReference,還有一些其他的方式,比如說減少static關鍵字的使用,在app中盡量去使用Application中的Context對象...避免線程不可控的情況發生,都是避免OOM的發生的方式...使用SoftReference更多的是在app中加載Bitmap而發生OOM...最后給大家一個源碼..這個源碼在上一篇文章發過了...這個源碼中不僅包含BitmapFactory.Options,還包括SoftReference...還有一些零碎的知識點...總之大家看了這個源碼...就能明白其中的道理....

 源碼:http://files.cnblogs.com/files/RGogoing/daimarufeng.zip

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM