Android開發(fā)優(yōu)化之的強引用漆魔、軟引用、弱引用的使用
2016.12.27 22:42*字數 1951閱讀 4371評論 16喜歡 122
nougat.png
引言
早在JDK1.2却音,Java就把對象的引用分為四種級別改抡,從而使程序能更加靈活的控制對象的生命周期。這四種級別由高到低依次為:強引用系瓢、軟引用雀摘、弱引用和虛引用。
但是平時我們的代碼中似乎很少出現(xiàn)這些, 而之前還看到過一份代碼中, 一個Activity中有一個靜態(tài)變量持有對自己的弱引用,來達到類似的singleTask的效果.
So, 是時候系統(tǒng)的學習一下軟引用八拱、弱引用這些,并對我們的代碼進行優(yōu)化了.
強引用
String str =newString("xiamin");
強引用是使用最普遍的引用。如果一個對象具有強引用,那垃圾回收器絕不會回收它肌稻。當內存空間不足清蚀,Java虛擬機寧愿拋出OutOfMemoryError錯誤,使程序異常終止爹谭,也不會靠隨意回收具有強引用的對象來解決內存不足的問題枷邪。
強引用特點:
強引用可以直接訪問目標對象。
強引用所指向的對象在任何時候都不會被系統(tǒng)回收诺凡。JVM寧愿拋出OOM異常东揣,也不會回收強引用所指向的對象。
強引用可能導致內存泄露腹泌。
軟引用 (SoftReference)
簡單用法
MyObject aRef =newMyObject();? ? SoftReference aSoftRef=newSoftReference(aRef);? ? ? ? MyObject anotherRef=(MyObject)aSoftRef.get();
java.lang.ref包中提供了幾個類:SoftReference類嘶卧、WeakReference類和PhantomReference類,它們分別代表軟引用凉袱、弱引用和虛引用芥吟。ReferenceQueue類表示引用隊列,它可以和這三種引用類聯(lián)合使用专甩,以便跟蹤Java虛擬機回收所引用的對象的活動钟鸵。
如果一個對象只具有軟引用,那么如果內存空間足夠涤躲,垃圾回收器就不會回收它棺耍;如果內存空間不足了,就會回收這些對象的內存种樱。只要垃圾回收器沒有回收它蒙袍,該對象就可以被程序使用。軟引用可用來實現(xiàn)內存敏感的高速緩存缸托。軟引用可以和一個引用隊列(ReferenceQueue)聯(lián)合使用左敌,如果軟引用所引用的對象被垃圾回收,Java虛擬機就會把這個軟引用加入到與之關聯(lián)的引用隊列中俐镐。
ReferenceQueue queue =newReferenceQueue();? ? SoftReference? ref=newSoftReference(aMyObject, queue);
那么當這個SoftReference所軟引用的aMyOhject被垃圾收集器回收的同時矫限,ref所強引用的SoftReference對象被列入ReferenceQueue。也就是說佩抹,ReferenceQueue中保存的對象是Reference對象叼风,而且是已經失去了它所軟引用的對象的Reference對象。另外從ReferenceQueue這個名字也可以看出棍苹,它是一個隊列无宿,當我們調用它的poll()方法的時候,如果這個隊列中不是空隊列枢里,那么將返回隊列前面的那個Reference對象孽鸡。
在任何時候蹂午,我們都可以調用ReferenceQueue的poll()方法來檢查是否有它所關心的非強可及對象被回收。如果隊列為空彬碱,將返回一個null,否則該方法返回隊列中前面的一個Reference對象豆胸。利用這個方法,我們可以檢查哪個SoftReference所軟引用的對象已經被回收巷疼。于是我們可以把這些失去所軟引用的對象的SoftReference對象清除掉晚胡。常用的方式為:
SoftReference ref =null;while((ref = (EmployeeRef) q.poll()) !=null) {// 清除ref}
當然,我們作為Android開發(fā)中使用,正常是用來處理圖片這種占用內存大的類的.
所以,我們應該這樣使用.
View view = findViewById(R.id.button);? ? Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);? ? Drawable drawable =newBitmapDrawable(bitmap);? ? SoftReference drawableSoftReference =newSoftReference(drawable);? ? ? ? Drawable bgdrawable = drawableSoftReference.get();if(bgdrawable !=null) {? ? ? ? view.setBackground(bgdrawable);? ? }
這樣的好處是
通過軟引用的get()方法,取得drawable對象實例的強引用嚼沿,發(fā)現(xiàn)對象被未回收估盘。在GC在內存充足的情況下,不會回收軟引用對象骡尽。此時view的背景顯示.
實際情況中,我們會獲取很多圖片.然后可能給很多個view展示, 這種情況下很容易內存吃緊導致oom,
內存吃緊遣妥,系統(tǒng)開始會GC。這次GC后爆阶,drawables.get()不再返回Drawable對象燥透,而是返回null,這時屏幕上背景圖不顯示辨图,說明在系統(tǒng)內存緊張的情況下班套,軟引用被回收。
使用軟引用以后故河,在OutOfMemory異常發(fā)生之前吱韭,這些緩存的圖片資源的內存空間可以被釋放掉的,從而避免內存達到上限鱼的,避免Crash發(fā)生理盆。
需要注意的是,在垃圾回收器對這個Java對象回收前凑阶,SoftReference類所提供的get方法會返回Java對象的強引用猿规,一旦垃圾線程回收該Java對象之后,get方法將返回null宙橱。所以在獲取軟引用對象的代碼中姨俩,一定要判斷是否為null,以免出現(xiàn)NullPointerException異常導致應用崩潰师郑。
弱引用 (WeakReference)
用法
WeakReference sr =newWeakReference(newUser());
如果一個對象只具有弱引用环葵,那么在垃圾回收器線程掃描的過程中,一旦發(fā)現(xiàn)了只具有弱引用的對象宝冕,不管當前內存空間足夠與否张遭,都會回收它的內存。不過地梨,由于垃圾回收器是一個優(yōu)先級很低的線程菊卷,因此不一定會很快發(fā)現(xiàn)那些只具有弱引用的對象缔恳。弱引用也可以和一個引用隊列(ReferenceQueue)聯(lián)合使用,如果弱引用所引用的對象被垃圾回收的烁,Java虛擬機就會把這個弱引用加入到與之關聯(lián)的引用隊列中褐耳。
弱引用與軟引用的根本區(qū)別在于:只具有弱引用的對象擁有更短暫的生命周期,可能隨時被回收渴庆。而只具有軟引用的對象只有當內存不夠的時候才被回收,在內存足夠的時候雅镊,通常不被回收襟雷。
使用場景,handler的使用防止內存泄露
importandroid.os.Bundle;importandroid.os.Handler;importandroid.os.Message;importandroid.support.v7.app.AppCompatActivity;importjava.lang.ref.WeakReference;publicclassMainActivityextendsAppCompatActivity{privateHandler handler? ;@OverrideprotectedvoidonCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);? ? ? ? setContentView(R.layout.activity_main);? ? ? ? handler =newMyHandler(this) ;newThread(newRunnable() {@Overridepublicvoidrun(){? ? ? ? ? ? ? handler.sendEmptyMessage(0) ;? ? ? ? ? ? }? ? ? ? }).start() ;? ? }privatestaticclassMyHandlerextendsHandler{? ? ? ? WeakReference weakReference ;publicMyHandler(MainActivity activity ){? ? ? ? ? ? weakReference? =newWeakReference( activity) ;? ? ? ? }@OverridepublicvoidhandleMessage(Message msg){super.handleMessage(msg);if( weakReference.get() !=null){// update android ui}? ? ? ? }? ? } }
在Android應用的開發(fā)中,為了防止內存溢出仁烹,在處理一些占用內存大而且聲明周期較長的對象時候耸弄,可以盡量應用軟引用和弱引用技術。
軟引用卓缰,弱引用都非常適合來保存那些可有可無的緩存數據计呈。如果這樣做,當系統(tǒng)內存不足時征唬,這些緩存數據會被回收捌显,不會導致內存溢出。而當內存資源充足時总寒,這些緩存數據又可以存在相當長的時間扶歪。
到底什么時候使用軟引用,什么時候使用弱引用呢摄闸?
個人認為善镰,如果只是想避免OutOfMemory異常的發(fā)生,則可以使用軟引用年枕。如果對于應用的性能更在意炫欺,想盡快回收一些占用內存比較大的對象,則可以使用弱引用熏兄。
還有就是可以根據對象是否經常使用來判斷品洛。如果該對象可能會經常使用的,就盡量用軟引用霍弹。如果該對象不被使用的可能性更大些毫别,就可以用弱引用。
另外典格,和弱引用功能類似的是WeakHashMap岛宦。WeakHashMap對于一個給定的鍵,其映射的存在并不阻止垃圾回收器對該鍵的回收耍缴,回收以后砾肺,其條目從映射中有效地移除挽霉。WeakHashMap使用ReferenceQueue實現(xiàn)的這種機制。
謝謝大家閱讀变汪,如有幫助侠坎,來個喜歡或者關注吧!
本文作者:Anderson/Jerey_Jobs
簡書地址? :Anderson大碼渣
CSDN地址? :Jerey_Jobs的專欄
github地址 :Jerey_Jobs
小禮物走一走裙盾,來簡書關注我
贊賞支持
? ? ? ? ? ? 著作權歸作者所有
5.2萬字 ·3.9萬閱讀·113人關注
? ? ? ?
? ? ? ?
? ? ? ? ? 更多分享