Android context

一個(gè)App里存在多少Context實(shí)例對(duì)象?

這次我們來(lái)探討一個(gè)問(wèn)題,一個(gè)應(yīng)用程序App中存在多少個(gè)Context實(shí)例對(duì)象呢?一個(gè)、兩個(gè)?
Activity類 、Service類 、Application類本質(zhì)上都是Context子類。
應(yīng)用程序創(chuàng)建Context實(shí)例的情況有如下幾種情況:

  • 創(chuàng)建Application對(duì)象時(shí), 而且整個(gè)App共一個(gè)Application對(duì)象
  • 創(chuàng)建Service對(duì)象時(shí)
  • 創(chuàng)建Activity對(duì)象時(shí)

1. 創(chuàng)建Application對(duì)象的時(shí)機(jī)
每個(gè)應(yīng)用程序在第一次啟動(dòng)時(shí),都會(huì)首先創(chuàng)建Application對(duì)象。創(chuàng)建Application的時(shí)機(jī)在創(chuàng)建handleBindApplication()方法中,該函數(shù)位于 ActivityThread.java 類中,如下:

//創(chuàng)建Application時(shí)同時(shí)創(chuàng)建的ContextIml實(shí)例  
private final void handleBindApplication(AppBindData data){  
    ...  
    ///創(chuàng)建Application對(duì)象  
    Application app = data.info.makeApplication(data.restrictedBackupMode, null);  
    ...  
}  

public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {  
    ...  
    try {  
        java.lang.ClassLoader cl = getClassLoader();  
        ContextImpl appContext = new ContextImpl();    //創(chuàng)建一個(gè)ContextImpl對(duì)象實(shí)例  
        appContext.init(this, null, mActivityThread);  //初始化該ContextIml實(shí)例的相關(guān)屬性  
        ///新建一個(gè)Application對(duì)象   
        app = mActivityThread.mInstrumentation.newApplication(  
                cl, appClass, appContext);  
       appContext.setOuterContext(app);  //將該Application實(shí)例傳遞給該ContextImpl實(shí)例           
    }   
    ...  
}

2.創(chuàng)建Activity對(duì)象的時(shí)機(jī)
通過(guò)startActivity()或startActivityForResult()請(qǐng)求啟動(dòng)一個(gè)Activity時(shí),如果系統(tǒng)檢測(cè)需要新建一個(gè)Activity對(duì)象時(shí),就會(huì)回調(diào)handleLaunchActivity()方法,該方法繼而調(diào)用performLaunchActivity()方法,去創(chuàng)建一個(gè)Activity實(shí)例,并且回調(diào)onCreate(),onStart()方法等, 函數(shù)都位于 ActivityThread.java類 ,如下:

//創(chuàng)建一個(gè)Activity實(shí)例時(shí)同時(shí)創(chuàng)建ContextIml實(shí)例  
private final void handleLaunchActivity(ActivityRecord r, Intent customIntent) {  
    ...  
    Activity a = performLaunchActivity(r, customIntent);  //啟動(dòng)一個(gè)Activity  
}  
private final Activity performLaunchActivity(ActivityRecord r, Intent customIntent) {  
    ...  
    Activity activity = null;  
    try {  
        //創(chuàng)建一個(gè)Activity對(duì)象實(shí)例  
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();  
        activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);  
    }  
    if (activity != null) {  
        ContextImpl appContext = new ContextImpl();      //創(chuàng)建一個(gè)Activity實(shí)例  
        appContext.init(r.packageInfo, r.token, this);   //初始化該ContextIml實(shí)例的相關(guān)屬性  
        appContext.setOuterContext(activity);            //將該Activity信息傳遞給該ContextImpl實(shí)例  
        ...  
    }  
    ...      
}

3.創(chuàng)建Service對(duì)象的時(shí)機(jī)
通過(guò)startService或者bindService時(shí),如果系統(tǒng)檢測(cè)到需要新創(chuàng)建一個(gè)Service實(shí)例,就會(huì)回調(diào)handleCreateService()方法,完成相關(guān)數(shù)據(jù)操作。handleCreateService()函數(shù)位于 ActivityThread.java類,如下:

//創(chuàng)建一個(gè)Service實(shí)例時(shí)同時(shí)創(chuàng)建ContextIml實(shí)例  
private final void handleCreateService(CreateServiceData data){  
    ...  
    //創(chuàng)建一個(gè)Service實(shí)例  
    Service service = null;  
    try {  
        java.lang.ClassLoader cl = packageInfo.getClassLoader();  
        service = (Service) cl.loadClass(data.info.name).newInstance();  
    } catch (Exception e) {  
    }  
    ...  
    ContextImpl context = new ContextImpl(); //創(chuàng)建一個(gè)ContextImpl對(duì)象實(shí)例  
    context.init(packageInfo, null, this);   //初始化該ContextIml實(shí)例的相關(guān)屬性  
    //獲得我們之前創(chuàng)建的Application對(duì)象信息  
    Application app = packageInfo.makeApplication(false, mInstrumentation);  
    //將該Service信息傳遞給該ContextImpl實(shí)例  
    context.setOuterContext(service);  
    ...  
}

強(qiáng)調(diào):
通過(guò)對(duì)ContextImp的分析可知,其方法的大多數(shù)操作都是直接調(diào)用其屬性mPackageInfo(該屬性類型為PackageInfo)的相關(guān)方法而來(lái)。這說(shuō)明ContextImp是一種輕量級(jí)類,而PackageInfo才是真正重量級(jí)的類。而一個(gè)App里的所有ContextIml實(shí)例,都對(duì)應(yīng)同一個(gè)packageInfo對(duì)象。

總結(jié):
通過(guò)前面的分析,可知一個(gè)應(yīng)用程序App共有的Context數(shù)目公式為:

 總Context實(shí)例個(gè)數(shù) = Service個(gè)數(shù) + Activity個(gè)數(shù) + 1(Application對(duì)應(yīng)的Context實(shí)例)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容