這是四大組件的第一篇(其他還沒整理好:) ),之前有個(gè)習(xí)慣,就是把一些筆記記在書上灭袁,但是隨著書越來越多猬错,翻閱的時(shí)候比較麻煩,尤其是一段時(shí)間不用之后简卧,想要翻閱某個(gè)知識(shí)點(diǎn)太費(fèi)勁兔魂,這里就打算統(tǒng)一整理在一起,方便查看举娩。
其中有很多內(nèi)容參照了網(wǎng)上的博文析校,但是時(shí)間比較久,忘記出處了铜涉。另外就是參照Android developer的相關(guān)文檔智玻,加上自己的理解,如果有錯(cuò)誤芙代,歡迎指出啊吊奢。
分類
Application的Context
Application對(duì)象以單例的形式出現(xiàn),代表正在運(yùn)行的APP纹烹,Application繼承了ContextWrapper页滚,所以可以認(rèn)為它也是一個(gè)Context,此處將其稱為“Application的Context”铺呵。
獲取方式:
在Activity或Service中裹驰,可通過調(diào)用getApplication()函數(shù)獲取。
可以通過context.getApplicationContext()獲取片挂。
Activity幻林、Service的Context
Activity和Service同樣都繼承于ContextWrapper贞盯,所以也可以認(rèn)為它們是Context。
BroadcastReceiver的Context
BroadcastReceiver本身不是Context沪饺,其內(nèi)部也不含有Context躏敢,但在onReceive(Context context, Intent intent)中有context參數(shù)。這個(gè)context隨著receiver的注冊(cè)方式的不同而不同:
靜態(tài)注冊(cè):context為ReceiverRestrictedContext整葡,bindService和registerReceiver被禁用
動(dòng)態(tài)注冊(cè):context為Activity的context
LocalBroadcastManager的動(dòng)態(tài)注冊(cè): context為Application的context
ContentProvider的Context
ContentProvider本身不是Context件余,但可以通過getContext()獲取一個(gè)context對(duì)象(該對(duì)象代表的是當(dāng)前provider運(yùn)行的context)。具體來講:
如果provider和調(diào)用者在同一個(gè)process中掘宪,context就是Application的context
如果provider和調(diào)用者分屬不同的進(jìn)程蛾扇,getContext將創(chuàng)建一個(gè)新的context代表此provider所運(yùn)行的包。
getContext()必須在onCreate調(diào)用之后才可用魏滚,在構(gòu)造器中調(diào)用將返回null镀首。
能力
Application | Activity | Service | Content Provider | Broadcast Receiver(靜態(tài)) | |
---|---|---|---|---|---|
顯示對(duì)話框 | No | Yes | No | No | No |
啟動(dòng)Activity | No1 | Yes | No1 | No1 | No1 |
填充布局 | No2 | Yes | No2 | No2 | No2 |
啟動(dòng)Service | Yes | Yes | Yes | Yes | Yes |
綁定Service | Yes | Yes | Yes | Yes | No |
發(fā)送Broadcast | Yes | Yes | Yes | Yes | Yes |
注冊(cè)Broadcast-Receiver | Yes | Yes | Yes | Yes | No3 |
加載資源值 | Yes | Yes | Yes | Yes | Yes |
注意:
- No1表示Application的Context確實(shí)可以啟動(dòng)一個(gè)Activity,但是它需要?jiǎng)?chuàng)建一個(gè)新的task鼠次,會(huì)造成APP中存在不標(biāo)準(zhǔn)的回退棧更哄,不推薦。
- No2表示這是非法的腥寇,填充雖然可以完成成翩,但使用的系統(tǒng)默認(rèn)的theme,而非APP的theme赦役。
- No3在4.2以上麻敌,如果receiver是null(用于粘性廣播,已被標(biāo)注為過時(shí))掂摔,是允許的术羔。
綜上:與UI相關(guān)的功能只能由Activity的Context去處理。
注意事項(xiàng)
當(dāng)需要保存一個(gè)context的引用時(shí)乙漓,如果它超過了你的Activity或Service的生命周期(即便只是暫時(shí)的)级历,需要保存Application的context。
比較典型的:?jiǎn)卫?/p>
錯(cuò)誤的例子:
public class CustomManager{
private static CustomManager sInstance;
private Context mContext;
private CustomManager(Context context){
mContext = context;
}
public static CustomManager getInstance(Context context){
if( sInstance == null ){
sInstance = new CustomManager(context);
}
return sInstance;
}
}
原因:如果傳入的context是一個(gè)Activity叭披,則由于它在單例的實(shí)現(xiàn)中被引用寥殖,導(dǎo)致該Activity對(duì)象及其所引用的對(duì)象永遠(yuǎn)不能被垃圾回收,有內(nèi)存泄漏的風(fēng)險(xiǎn)涩蜘。
更好的實(shí)現(xiàn):
public class CustomManager{
private static CustomManager sInstance;
private Context mContext;
private CustomManager(Context context){
mContext = context;
}
public static CustomManager getInstance(Context context){
if( sInstance == null ){
sInstance = new CustomManager(context.getApplicationContext());
}
return sInstance;
}
}
另一個(gè)比較典型的例子:在后臺(tái)線程或一個(gè)等待的Handler中如果需要保存Context的引用嚼贡,也請(qǐng)使用Application的context。