1. 為什么context使用不當(dāng)會導(dǎo)致內(nèi)存泄漏
我們在日常開發(fā)中,經(jīng)常用到單例模式,由于單例的靜態(tài)特性使得其生命周期跟應(yīng)用的生命周期一樣長,所以如果使用不恰當(dāng)?shù)脑?,很容易造成?nèi)存泄漏。比如下面一個典型的例子,
public class AppManager {
private static AppManager instance;
private Context context;
private AppManager(Context context) {
this.context = context;
}
public static AppManager getInstance(Context context) {
if (instance == null) {
instance = new AppManager(context);
}
return instance;
}
}
這是一個普通的單例模式,當(dāng)創(chuàng)建這個單例的時候,由于需要傳入一個Context,所以這個Context的生命周期的長短至關(guān)重要:
1、如果此時傳入的是 Application 的 Context,因?yàn)?Application 的生命周期就是整個應(yīng)用的生命周期,所以這將沒有任何問題。
2、如果此時傳入的是 Activity 的 Context,當(dāng)這個 Context 所對應(yīng)的 Activity 退出時,由于該 Context 的引用被單例對象所持有,其生命周期等于整個應(yīng)用程序的生命周期,所以當(dāng)前 Activity 退出時它的內(nèi)存并不會被回收,這就造成泄漏了。
正確的方式應(yīng)該改為下面這種方式:
public class AppManager {
private static AppManager instance;
private Context context;
private AppManager(Context context) {
this.context = context.getApplicationContext();// 使用Application 的context
}
public static AppManager getInstance(Context context) {
if (instance == null) {
instance = new AppManager(context);
}
return instance;
}
}
2. Context的分類和作用域

其中: NO1表示 Application 和 Service 可以啟動一個 Activity,不過需要創(chuàng)建一個新的 task 任務(wù)隊(duì)列。而對于 Dialog 而言,只有在 Activity 中才能創(chuàng)建。
一句話總結(jié):凡是跟UI相關(guān)的,都應(yīng)該使用Activity做為Context來處理。
3. 如何在我們的應(yīng)用中獲取application的context
(1) 如果是在Activity和Service中,可以直接使用getApplicationContext()方法得到;
(2) 如果是在Receiver中,在onReceive(Context context, Intent intent)中會返回一個context實(shí)例,然后使用context.getApplicationContext()方法得到。
(3) 如果是在其它的一般類中,學(xué)生端請使用UIApplication.getInstance()得到。老師端請使用MApplication.getInstance()得到。
4. Context 簡介以及正確使用注意點(diǎn)

Context的正確使用要點(diǎn):
(1) 當(dāng)Application的Context能搞定的情況下,并且生命周期長的對象,優(yōu)先使用Application的Context。
(2) 不要讓生命周期長于Activity的對象持有到Activity的引用。
(3) 盡量不要在Activity中使用非靜態(tài)內(nèi)部類,因?yàn)榉庆o態(tài)內(nèi)部類會隱式持有外部類實(shí)例的引用,如果使用靜態(tài)內(nèi)部類,將外部實(shí)例引用作為弱引用持有。