Android開發(fā)之什么是context

今天研究了一下Context類,對于context發(fā)現(xiàn)即熟悉又陌生。一個我們天天打交道的東西到底是什么呢,這篇文章將帶大家了解context。

簡介

我們先看google官方的說明

/**
 * 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.
 */
public abstract class Context

從上可知一下三點,即:
1、它描述的是一個應(yīng)用程序環(huán)境的信息,即上下文。
2、該類是一個抽象(abstract class)類,Android提供了該抽象類的具體實現(xiàn)類(后面我們會講到是ContextIml類)。
3、通過它我們可以獲取應(yīng)用程序的資源和類,也包括一些應(yīng)用級別操作,例如:啟動一個Activity,發(fā)送廣播,接受Intent 信息 等。。

那么我們明確第一點,context是一個抽象類,而我們平時用的context,均是其實現(xiàn),而更偉大的是, 我們的application,我們的activity,service,均在context的繼承關(guān)系樹的。
讓我們看一張類圖,相信看完這個類圖大家就知道context在我們的應(yīng)用中是什么樣子的地位:

context繼承關(guān)系圖

通過看圖,我們知道了,一個應(yīng)用程序App共有的Context數(shù)目公式為:

                 總Context實例個數(shù) = Service個數(shù) + Activity個數(shù) + 1(Application對應(yīng)的Context實例)

可見,我們的每個Activity,Service,Application都有自己的context,那么context是什么時候傳入的呢?

Context的傳入

1.創(chuàng)建Application對象的時機

每個應(yīng)用程序在第一次啟動時,都會首先創(chuàng)建Application對象。在應(yīng)用程序啟動Activity(startActivity)流程中,創(chuàng)建Application的時機在創(chuàng)建handleBindApplication()方法中,該函數(shù)位于 ActivityThread.java類中 ,如下:

//創(chuàng)建Application時同時創(chuàng)建的ContextIml實例  
private final void handleBindApplication(AppBindData data){  
    ...  
    ///創(chuàng)建Application對象  
    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)建一個ContextImpl對象實例  
        appContext.init(this, null, mActivityThread);  //初始化該ContextIml實例的相關(guān)屬性  
        ///新建一個Application對象   
        app = mActivityThread.mInstrumentation.newApplication(  
                cl, appClass, appContext);  
       appContext.setOuterContext(app);  //將該Application實例傳遞給該ContextImpl實例           
    }   
    ...  
}  

2、創(chuàng)建Activity對象的時機

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

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

3、創(chuàng)建Service對象的時機

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

//創(chuàng)建一個Service實例時同時創(chuàng)建ContextIml實例  
private final void handleCreateService(CreateServiceData data){  
    ...  
    //創(chuàng)建一個Service實例  
    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)建一個ContextImpl對象實例  
    context.init(packageInfo, null, this);   //初始化該ContextIml實例的相關(guān)屬性  
    //獲得我們之前創(chuàng)建的Application對象信息  
    Application app = packageInfo.makeApplication(false, mInstrumentation);  
    //將該Service信息傳遞給該ContextImpl實例  
    context.setOuterContext(service);  
    ...  
}  

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


本文作者:Jerey_Jobs

簡書地址:Anderson大碼渣

github地址:Jerey_Jobs

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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