一:什麼是Context?
Context,sdk中的解釋如下:interface to global information about an application environment.This is an abstract class whose implementation is provided by the Android System.It allows access to application-specific resources and classes,as well as up-calls for application-level operations such as launching activities,broadcasting and receiving intents,etc.
簡單的總結爲三條:
1.它描述的是一個應用程序的環境的信息,可以被稱作爲上下文。
2.該類是一個抽象類,Android提供了該抽象類的具體實現類。
3.通過它我們可以獲取應用程序的資源和類,也包括採取一些應用級別的操作,例如,啓動一個Activity,發送廣播,接收Intent.
二:Context抽象類的繼承關係
由上圖我們可以看出,Activity,service,Application實則全爲Context的子類。
三:Context實例的創建時機以及數目
通常來說,程序創建Context實例的時機爲以下三種情況:
1.創建Application對象時,而且整個App共有一個Application對象。
2.創建Service對象時
3.創建Activity對象時
由上可知,一個應用程序中Context實例個數的計算公式爲:
總Context數 = Service個數 + Activity個數 + 1(Application對應的Context實例)
四:Context的獲取方式以及全局獲取Context的技巧
因爲Activity,Service本身就是一個context對象,所以在其中獲取Context非常簡單,但當脫離了這些與Context類有緊密關係的類時,我們該如何獲得呢?當然這也有許多方法可以獲得,但我在此給大家分享一種方法,定製一個自己的Application類,以便於管理程序內一些全局的狀態信息,如Context。創建一個MyApplication繼承自Application,代碼如下:(以下代碼來自《第一行代碼》)
public class MyApplication extends Application{
private static Context context;
@override
public void onCreate(){
context = getApplicationContext();
}
public static Context getContext(){
return context;
}
}
接下來我們需要告知系統,當程序啓動的時候應該初始化MyApplication而不是默認的Application類,操作也很簡單,修改AndroidManifest.xml文件的<application>標籤下的內容:
<application
android:name="com.example.hhw.MyApplication"
....>
</appliaction>
之後,你可以通過以下方式在你想用Context的任何地方得到它。
<span style="font-size:14px;">MyApplication.getContext();</span>
五:Activity,Application的Context以及內存泄露
首先,Activity的Context和Application的Context肯定不是一個東西,一個是當前活動的Context,它的生命週期僅限於此活動,一個是整個應用程序的Context,它的生命週期伴隨着整個程序,鑑於Activity的Context的特點,濫用它往往會造成內存泄露,如下代碼所示:
<span style="font-size:14px;">public class TestContext{
private static TestContext testContext;
private Context context;
private TestContext(Context context){
this.context = context;
}
public static synchronized TestContext getInstance(Context context){
if(null == testContext)
testContext = new TestContext(context);
return testContext;
}
}</span>
顯而易見,上述單例模式中textContext是強引用static類型,往往它的生命週期伴隨着整個應用程序,但你傳遞進來的Context若是一個Activity的,只要我們這個應用程序還活着,它就沒有辦法正常的回收,這就造成了內存的泄露。解決的方法很簡單,將初始化TestContext是傳遞的參數變爲context.getApplicationContext()既可,因爲用此方法獲得的是應用程序的context,因此就不用擔心內存泄露了。
public class TestContext{
private static TestContext testContext;
private Context context;
private TestContext(Context context){
this.context = context;
}
public static synchronized TestContext getInstance(Context context){
if(null == testContext)
testContext = new TestContext(context.getApplicationContext());
return testContext;
}
}
既然如此的話,在能使用context的地方全部替換成context.getApplicationContext()不就皆大歡喜了嗎?很遺憾的來說,這樣不行,因爲他們根本不是一個東西,它們的應用場景是不同的,並非所有的Activity的Context的場景,Application的Context依然可以,一下是我總結出來的一個表格,表示了它倆之間的應用場景:
Application | Activity | |
show a dialog | NO | YES |
Layout Inflation | NO | YES |
start an activity | NO | YES |
Bild to a Service | YES | YES |
Send a Broadcast | YES | YES |
Register BrocastReceiver | YES | YES |
start a service | YES | YES |
load resource values | YES | YES |
1.凡是和UI相關的,都不建議使用Application的Context.
2..不要讓生命週期長的對象引用activity context,即保證引用activity的對象要與activity本身生命週期是一樣的,若不一樣,請考慮一下是否可以使用Application的Context.