Application中的 Context 和 Activity 中的Context區(qū)別

一惊奇、基礎知識

Context在我們開發(fā)中經常用到烙样,不管是Framework提供給我們的四大組件,還是應用級別的Application脐往,還是負責表現(xiàn)層的View相關類休吠,甚至連我們很多時候創(chuàng)建的實體類都會需要持有一個Context的引用。那么Context到底是什么呢业簿?

建議看這個:http://www.reibang.com/p/b68de4c95b05

(1)Context是什么瘤礁?

Context英文釋義是當前上下文,或者當前場景上梅尤,
官方文檔:Context

public abstractclass Context extends Object

Interface to globalinformation about an application environment. This is an abstract class whoseimplementation is provided by the Android system. It allows access toapplication-specific resources and classes, as well as up-calls forapplication-level operations such as launching activities, broadcasting andreceiving intents, etc.

由官方文檔柜思,我們可以知道:
1.該類是一個抽象(abstract class)類
2.它描述的是一個應用程序環(huán)境的信息巷燥,即上下文赡盘;
3.通過它(Context)我們可以獲取應用程序的資源和類,也包括一些應用級別的操作(例如缰揪,啟動 Activity,廣播和服務等);

(2) Context有什么用陨享?

前面我們講過 Context 是一個抽象類,通過 Context我們可以獲取應用程序的資源和類钝腺,調用它們的方法抛姑,那么具體定義的方法有哪些呢?我們來看一下 Context 的源碼:

public abstract class Context {
 
    public abstract void startActivity(Intent intent);
    public abstract void startActivity(Intent intent, @Nullable Bundle options);
    public abstract void startActivities(Intent[] intents);
    public abstract void startActivities(Intent[] intents, Bundle options);
    public abstract void sendBroadcast(Intent intent);
    public abstract void sendBroadcast(Intent intent,
            @Nullable String receiverPermission);
    public abstract Intent registerReceiver(@Nullable BroadcastReceiver receiver,
                                            IntentFilter filter);
    public abstract void unregisterReceiver(BroadcastReceiver receiver);

    public final String getString(@StringRes int resId) ;
    public final int getColor(@ColorRes int id) ;
    public final Drawable getDrawable(@DrawableRes int id);
    public abstract void setTheme(@StyleRes int resid);
    public abstract ApplicationInfo getApplicationInfo();
    public abstract String getPackageName();
    public abstract String getPackageResourcePath();
    public File getSharedPrefsFile(String name) ;
    public abstract SharedPreferences getSharedPreferences(String name, @PreferencesMode int mode);

    ......
    ......
}

源碼里的方法太多了艳狐,總共 4710 行定硝。我們從以上部分源碼看到了熟悉的對象---Application、Activity毫目、Service蔬啡、Broadcast、這些對象和 Context 的關系到底是什么呢蒜茴?我們看一下官方文檔可知:


20180410160701954.png

總結:

1.Acitiivity 繼承自ContextThemeWrapper--->再繼承ContextWrapper--->Context星爪。
2.Appliction 、Service繼承自ContextWrapper--->再繼承Context粉私。
3.Application顽腾、Service 和 Activity 最終都是繼承自Context,所以它們是同一個上下文。

通過以上的繼承關系抄肖,我們就可以知道久信,Context的具體作用會包括:
- 啟動一個新的Activity
- 啟動和停止Service
- 發(fā)送廣播消息(Intent)
- 注冊廣播消息(Intent)接收者
- 可以訪問APK中各種資源,如Resources和AssetManager
- 創(chuàng)建View
- 訪問Package的相關信息
- APK的各種權限管理

(3)Context 創(chuàng)建時機漓摩?

由上面分析的繼承關系裙士,我們可以知道,Context創(chuàng)建的時機有三個:

①創(chuàng)建Application 對象時管毙, 而且整個App共一個Application對象腿椎;

②創(chuàng)建Service對象時;

③創(chuàng)建Activity對象時夭咬;

所以應用程序App共有的Context數目公式為:

Service個數 + Activity個數 + 1(Application對應的Context實例)

二啃炸、Context 使用時注意事項:

(1)Context 使用時注意什么?

如上卓舵,Android中context可以作很多操作南用,但是最主要的功能是加載和訪問資源。在android中常用的context有兩種掏湾,一種是application context裹虫,一種是activity context,通常我們在各種類和方法間傳遞的是activity context融击。

兩者的區(qū)別:

public class MyActivity extends Activity {  
    public void method() {  
        mContext = this; // since Activity extends Context  
        mContext = getApplicationContext();  
    }  
}

this是Activity 的實例筑公,擴展了Context,其生命周期是Activity 創(chuàng)建到銷毀砚嘴。getApplicationContext()返回應用的上下文十酣,生命周期是整個應用,應用摧毀它才被摧毀际长。Activity.this的context 返回當前activity的上下文耸采,屬于activity ,activity摧毀時被摧毀工育。

使用Context時最需要注意的一個點就是虾宇,使用了不正確的context,比如有一個全局的數據操作類用到了context如绸,這個時候就要getApplicationContext 而不是用ACtivity嘱朽,如果在這個全局操作中引用的是Activity的context,那么就會一直引用Activity的資源怔接,導致GC無法回收這部分內存搪泳,從而最終導致了內存泄漏

內存泄漏是開發(fā)中常見的錯誤之一扼脐,能不能發(fā)現(xiàn)取決于開發(fā)者的經驗岸军,當然了我們也會依賴現(xiàn)有的內存泄漏庫奋刽,但是如果我們在開發(fā)的源頭減少內存泄漏的概率,那么后期的工作會少很多艰赞。

以下是避免context相關的內存泄露佣谐,給出的幾點建議:

  • 不要讓生命周期長的對象引用activity context,即保證引用activity的對象要與activity本身生命周期是一樣的方妖;
  • 對于生命周期長的對象狭魂,可以使用application context;
  • 避免非靜態(tài)的內部類党觅,盡量使用靜態(tài)類雌澄,避免生命周期問題,注意內部類對外部對象引用導致的生命周期變化仔役;

(2)Context的常見應用場景

以下的表列舉的是三種Context對象的對應使用場景:

image.png

從表中可以看到掷伙,和UI相關的都使用Activity的Context對象。

小結:如上分析又兵,Context在對應開發(fā)里的來源就是三個——Activity、Service和Appliaction卒废,那么我們該如何選擇使用哪一個Context對象呢沛厨?一個比較簡單的方法是,當你無法確定使用某個Context對象是否會造成長引用導致內存泄漏時摔认,那么就使用Appliaction的Context對象逆皮,因為Appliaction存在于整個應用的生命周期內。

三参袱、實際開發(fā)中用到自定義 Application

在實際開發(fā)中电谣,我們往往會為項目定義一個Applictaion,然后在AndroidMainfest.xml文件中進行注冊抹蚀,

<application
        android:name=".MyApplication"
        android:label="@string/app_name"
        android:theme="@style/AppThemeLight">
...
</application>

而且在自定義Application往往會定義好一個靜態(tài)方法剿牺,用以全局獲取application實例:

public class MyApplication extends Application {
    
    private static MyApplication myApplication ;
    
    public static MyApplication getInstance() {
        return myApplication ;
    }
    
    @Override
    public void onCreate() {
        super.onCreate();
        myApplication = this;
    }
    
}

Activity和Application都是Context的子類,但是他們維護的生命周期不一樣环壤。前者維護一個Acitivity的生命周期晒来,所以其對應的Context也只能訪問該activity內的各種資源。后者則是維護一個Application的生命周期郑现。

附錄:其他一些方法和使用context的注意事項

1.如何判斷context是屬于哪個activity湃崩?

context.getClass().getSimpleName()

2.全局不同如何獲取對應的context?

  • View.getContext()接箫,返回當前View對象的Context對象攒读,通常是當前正在展示的Activity對象,這個是View類中提供的方法辛友,在繼承了View的類中才可以調用薄扁,返回的是當前View運行在哪個Activity Context中;

  • Activity.getApplicationContext(),獲取當前Activity所在的(應用)進程的Context對象泌辫,通常我們使用Context對象時随夸,要優(yōu)先考慮這個全局的進程Context;

  • ContextWrapper.getBaseContext():用來獲取一個ContextWrapper進行裝飾之前的Context震放,可以使用這個方法宾毒,這個方法在實際開發(fā)中使用并不多,也不建議使用殿遂;

  • Activity.this 诈铛,表示Activity對象,一般用在內部類中指示外面的this墨礁,如果在內部類直接用this幢竹,指示的是內部類本身;

  • this恩静,表示當前對象焕毫;一般而言,在哪個類中調用驶乾,就是指向該對象邑飒;

  • getActivity(),Fragment中级乐,返回Fragment綁定的Activity;

靜態(tài)加載一個Fragment疙咸,在onCreateView()方法中通過getActivity獲取上下文實例:

public class CollageFragment extends Fragment {
    private CameraPreviewActivity activity;
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        root_view = inflater.inflate(R.layout.fragment_collage, container, false);
        activity = (CameraPreviewActivity) getActivity();
        init();
        return root_view;
    }
 
    private void init() {
        // 利用此activity發(fā)送廣播
        activity.sendBroadcast(new Intent(CameraPreviewActivity.REMOVE_SCENES_EFFECT_WHEN_NOT_FULL_MODE));
                    MobClickUtil.onEvent(activity,"main_click_11");
        // 調用此activity的實例方法
        activity.setRatio("1x1",0);
    }    
}

3.四大組件可以像普通Java類一樣,采用new的方式實例化嗎风科?

Android程序不像Java程序一樣撒轮,隨便創(chuàng)建一個類,寫個main()方法就能運行贼穆,Android應用模型是基于組件的應用設計模式题山,組件的運行要有一個完整的Android工程環(huán)境,在這個環(huán)境下扮惦,Activity臀蛛、Service等系統(tǒng)組件才能夠正常工作,而這些組件并不能采用普通的Java對象創(chuàng)建方式崖蜜,new一下就能創(chuàng)建實例了浊仆,而是要有它們各自的上下文環(huán)境,也就是我們這里討論的Context豫领÷帐粒可以這樣講,Context是維持Android程序中各組件能夠正常工作的一個核心功能類等恐。

參考 作者:Chin_style
原文:https://blog.csdn.net/weixin_41101173/article/details/7988284

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末洲劣,一起剝皮案震驚了整個濱河市备蚓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌囱稽,老刑警劉巖郊尝,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異战惊,居然都是意外死亡流昏,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進店門吞获,熙熙樓的掌柜王于貴愁眉苦臉地迎上來况凉,“玉大人,你說我怎么就攤上這事各拷〉笕蓿” “怎么了?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵烤黍,是天一觀的道長知市。 經常有香客問我,道長蚊荣,這世上最難降的妖魔是什么初狰? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮互例,結果婚禮上,老公的妹妹穿的比我還像新娘筝闹。我一直安慰自己媳叨,他們只是感情好,可當我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布关顷。 她就那樣靜靜地躺著糊秆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪议双。 梳的紋絲不亂的頭發(fā)上痘番,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天,我揣著相機與錄音平痰,去河邊找鬼汞舱。 笑死,一個胖子當著我的面吹牛宗雇,可吹牛的內容都是我干的昂芜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼赔蒲,長吁一口氣:“原來是場噩夢啊……” “哼泌神!你這毒婦竟也來了良漱?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤欢际,失蹤者是張志新(化名)和其女友劉穎母市,沒想到半個月后,有當地人在樹林里發(fā)現(xiàn)了一具尸體损趋,經...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡患久,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了舶沿。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片墙杯。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖括荡,靈堂內的尸體忽然破棺而出高镐,到底是詐尸還是另有隱情,我是刑警寧澤畸冲,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布嫉髓,位于F島的核電站,受9級特大地震影響邑闲,放射性物質發(fā)生泄漏算行。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一苫耸、第九天 我趴在偏房一處隱蔽的房頂上張望州邢。 院中可真熱鬧,春花似錦褪子、人聲如沸量淌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽呀枢。三九已至,卻和暖如春笼痛,著一層夾襖步出監(jiān)牢的瞬間裙秋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工缨伊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留摘刑,地道東北人。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓倘核,卻偏偏與公主長得像泣侮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子紧唱,可洞房花燭夜當晚...
    茶點故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內容