public class SampleActivity extends Activity {
/**
* Instances of static inner classes do not hold an implicit
* reference to their outer class.
*/
private static class MyHandler extends Handler {
private final WeakReference<SampleActivity> mActivity;
public MyHandler(SampleActivity activity) {
mActivity = new WeakReference<SampleActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
SampleActivity activity = mActivity.get();
if (activity != null) {
// ...
}
}
}
private final MyHandler mHandler = new MyHandler(this);
/**
* Instances of anonymous classes do not hold an implicit
* reference to their outer class when they are "static".
*/
private static final Runnable sRunnable = new Runnable() {
@Override
public void run() { /* ... */ }
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Post a message and delay its execution for 10 minutes.
mHandler.postDelayed(sRunnable, 1000 * 60 * 10);
// Go back to the previous Activity.
finish();
}
}
這里Handler為什么要用弱引用來持有Activity的引用?和使用軟引用有什么區(qū)別?
這里使用弱引用持有Activity,就是表示Handler不會占用著對activity的引用而導(dǎo)致系統(tǒng)無法回收,只要系統(tǒng)來回收這個Activity就能回收掉僧叉。
在我的理解,使用弱引用而不是軟引用棺榔,表示Handler將Activity回收權(quán)完全地交給組件管理系統(tǒng):系統(tǒng)什么時候回收Activity我不知道瓶堕,反正我不占用,只要你GC來回收時就能回收掷豺。
如果Activity被回收了捞烟,會對Handler業(yè)務(wù)邏輯有影響嗎?這里需要考慮到情形当船。什么時候GC會來回收Activity题画?這時應(yīng)該是用戶已經(jīng)退出或者跳出了這個Activity,而內(nèi)存緊張德频,組件管理系統(tǒng)判斷需要這個Activity了苍息。
Handler的handleMessage()一般是在異步消息返回后更新數(shù)據(jù)操作的,這時如果Activity已經(jīng)隱入后臺了壹置,一般也不再需要UI或數(shù)據(jù)的更新了竞思。當(dāng)然如果需要這個Activity常駐內(nèi)存,當(dāng)用戶回到這個Activity可以看到更新后的數(shù)據(jù)钞护,可以使用其他方法盖喷。
強(qiáng)引用
只要某個對象有強(qiáng)引用與之關(guān)聯(lián),JVM必定不會回收這個對象难咕,即使在內(nèi)存不足的情況下课梳,JVM寧愿拋出OutOfMemory錯誤也不會回收這種對象。
如果想中斷強(qiáng)引用和某個對象之間的關(guān)聯(lián)余佃,可以顯示地將引用賦值為null暮刃,這樣一來的話,JVM在合適的時間就會回收該對象爆土。
軟引用
軟引用在Java中用java.lang.ref.SoftReference類來表示椭懊。
對于軟引用關(guān)聯(lián)著的對象,只有在內(nèi)存不足的時候JVM才會回收該對象步势。因此氧猬,這一點可以很好地用來解決OOM的問題背犯,并且這個特性很適合用來實現(xiàn)緩存:比如網(wǎng)頁緩存、圖片緩存等狂窑。
軟引用可以和一個引用隊列(ReferenceQueue)聯(lián)合使用媳板,如果軟引用所引用的對象被JVM回收桑腮,這個軟引用就會被加入到與之關(guān)聯(lián)的引用隊列中泉哈。
import java.lang.ref.SoftReference;
public class Main {
public static void main(String[] args) {
SoftReference<String> sr = new SoftReference<String>(new String("hello"));
System.out.println(sr.get());
}
}
弱引用
弱引用用java.lang.ref.WeakReference類來表示。
當(dāng)JVM進(jìn)行垃圾回收時破讨,無論內(nèi)存是否充足丛晦,都會回收被弱引用關(guān)聯(lián)的對象。
import java.lang.ref.WeakReference;
public class Main {
public static void main(String[] args) {
WeakReference<String> sr = new WeakReference<String>(new String("hello"));
System.out.println(sr.get());
System.gc(); //通知JVM的gc進(jìn)行垃圾回收
System.out.println(sr.get());
}
}
輸出結(jié)果
hello
null
第二個輸出結(jié)果是null提陶,這說明只要JVM進(jìn)行垃圾回收烫沙,被弱引用關(guān)聯(lián)的對象必定會被回收掉。
虛引用
虛引用在java中用java.lang.ref.PhantomReference類表示隙笆。
虛引用并不影響對象的生命周期锌蓄。如果一個對象與虛引用關(guān)聯(lián),則跟沒有引用與之關(guān)聯(lián)一樣撑柔,在任何時候都可能被垃圾回收器回收瘸爽。
要注意的是,虛引用必須和引用隊列關(guān)聯(lián)使用铅忿,當(dāng)垃圾回收器準(zhǔn)備回收一個對象時剪决,如果發(fā)現(xiàn)它還有虛引用,就會把這個虛引用加入到與之 關(guān)聯(lián)的引用隊列中檀训。程序可以通過判斷引用隊列中是否已經(jīng)加入了虛引用柑潦,來了解被引用的對象是否將要被垃圾回收。如果程序發(fā)現(xiàn)某個虛引用已經(jīng)被加入到引用隊列峻凫,那么就可以在所引用的對象的內(nèi)存被回收之前采取必要的行動渗鬼。
軟引用和弱引用的區(qū)別
它們都是用來描述非必需對象的,但是被軟引用關(guān)聯(lián)的對象只有在內(nèi)存不足時才會被回收荧琼,而被弱引用關(guān)聯(lián)的對象在JVM進(jìn)行垃圾回收時總會被回收譬胎。
引用類的使用
在SoftReference類中,有三個方法铭腕,兩個構(gòu)造方法和一個get方法(WekReference類似):
兩個構(gòu)造方法:
public SoftReference(T referent) {
super(referent);
this.timestamp = clock;
}
public SoftReference(T referent, ReferenceQueue<? super T> q) {
super(referent, q);
this.timestamp = clock;
}
get方法用來獲取與軟引用關(guān)聯(lián)的對象的引用银择,如果該對象被回收了,則返回null累舷。
在使用軟引用和弱引用的時候浩考,我們可以顯示地通過System.gc()來通知JVM進(jìn)行垃圾回收。要注意的是被盈,雖然發(fā)出了通知析孽,JVM不一定會立刻執(zhí)行搭伤。