版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
Android應(yīng)用程序窗口(Activity)的運(yùn)行上下文環(huán)境(Context)的創(chuàng)建過程分析在前文中,我們簡要介紹了 Android應(yīng)用程序窗口的框架。 Android應(yīng)用程序窗口在運(yùn)行的過程中,需要訪問一些特定的資源或者類。 這些特定的資源或者類構(gòu)成了 Android應(yīng)用程序的運(yùn)行上下文環(huán)境,Android應(yīng)用程序窗口可以通過一個 Context接口來訪問它,這個Context接口也是我們在開發(fā)應(yīng)用程序時經(jīng)常碰到的。 在本文中,我們就將詳細(xì)分析 Android應(yīng)用程序窗口的運(yùn)行上下文環(huán)境的創(chuàng)建過程。在前面一文中提到, Android 應(yīng)用程序窗口的運(yùn)行上下文環(huán)境是通過 ContextImpl類來描述的,即每一個 Activity 組件都關(guān)聯(lián)有一個 ContextImpl對象。ContextImpl類繼承了Context類,它與 Activity 組件的關(guān)系如圖 1所示:這個類圖在設(shè)計模式里面就可以稱為裝飾模式。Activity組件通過其父類ContextThemeWrapper和ContextWrapper的成員變量mBase來引用了一個ContextImpl對象,這樣,Activity組件以后就可以通過這個ContextImpl對象來執(zhí)行一些具體的操作,例如,和等操作。同時,ContextImpl類又通過自己的成員變量mOuterContext來引用了與它關(guān)聯(lián)的一個Activity組件,這樣,ContextImpl類也可以將一些操作轉(zhuǎn)發(fā)給Activity組件來處理。在前面一文中,我們已經(jīng)詳細(xì)分析過一個 Activity 組件的啟動過程了。在這個啟動過程中,最后一步便是通過 ActivityThread 類的成員函數(shù) performLaunchActivity 在應(yīng)用程序進(jìn)程中創(chuàng)建一個 Activity 實(shí)例,并且為它設(shè)置運(yùn)行上下文環(huán)境, 即為它創(chuàng)建一個 ContextImpl對象。接下來,我們就從 ActivityThread 類的成員函數(shù) performLaunchActivity 開始,分析一個Activity 實(shí)例的創(chuàng)建過程,以便可以從中了解它的運(yùn)行上下文環(huán)境的創(chuàng)建過程, 如圖2所示:這個過程一共分為 10個步驟,接下來我們就詳細(xì)分析每一個步驟。Step1.ActivityThread.performLaunchActivity[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicfinalclassActivityThread{......InstrumentationmInstrumentation;......privatefinalActivityperformLaunchActivity(ActivityClientRecordr,IntentcustomIntent){............Activityactivity=null;try{activity=mInstrumentation.newActivity(cl,component.getClassName(),ent);......}catch(Exceptione){......}try{......if(activity!=null){ContextImplappContext=newContextImpl();......appContext.setOuterContext(activity);......Configurationconfig=newConfiguration(mConfiguration);......activity.attach(appContext,this,getInstrumentation(),r.token,r.ident,app,ent,r.activityInfo,title,r.parent,r.embeddedID,r.lastNonConfigurationInstance,r.lastNonConfigurationChildInstances,config);......mInstrumentation.callActivityOnCreate(activity,r.state);......}......}catch(SuperNotCalledExceptione){......}catch(Exceptione){......}returnactivity;}}這個函數(shù)定義在文件 frameworks/base/core/Java/android/app/ActivityThread.java 中。要啟動的 Activity 組件的類名保存在變量 component。有了這個類名之后,函數(shù)就可以調(diào)用ActivityThread類的成員變量mInstrumentation所描述一個Instrumentation對象的成員函數(shù)newActivity來創(chuàng)建一個Activity組件實(shí)例了,并且保存變量activity中。Instrumentation類是用來記錄應(yīng)用程序與系統(tǒng)的交互過程的, 在接下來的 Step2中,我們再分析它的成員函數(shù)newActivity的實(shí)現(xiàn)。創(chuàng)建好了要啟動的 Activity 組件實(shí)例之后,函數(shù)接下來就可以對它進(jìn)行初始化了。初始化一個 Activity 組件實(shí)例需要一個 Application 對象 app、一個 ContextImpl 對象appContext以及一個 Configuration對象config,它們分別用來描述該 Activity 組件實(shí)例的應(yīng)用程序信息、運(yùn)行上下文環(huán)境以及配置信息。 這里我們主要關(guān)心運(yùn)行上下文環(huán)境的創(chuàng)建過程,即ContextImpl對象appContext的創(chuàng)建過程,這個過程我們在接下來的 Step4中再分析。ContextImpl 對象 appContext 創(chuàng)建完成之后,函數(shù)就會調(diào)用它的成員函數(shù)setOuterContext來將與它所關(guān)聯(lián)的 Activity 組件實(shí)例 activity 保存在它的內(nèi)部。這樣,ContextImpl對象appContext以后就可以訪問與它所關(guān)聯(lián)的 Activity 組件的屬性或者方法。在接下來的 Step5中,我們再分析 ContextImpl類的成員函數(shù) setOuterContext的實(shí)現(xiàn)。接著,函數(shù)就調(diào)用 Activity 組件實(shí)例 activity 的成員函數(shù) attach來將前面所創(chuàng)建的ContextImpl對象appContext以及Application對象app和Configuration對象config保存在它的內(nèi)部。這樣,Activity 組件實(shí)例 activity就可以訪問它的運(yùn)行上下文環(huán)境信息了。 在接下來的Step6中,我們再分析 Activity 類的成員函數(shù) attach的實(shí)現(xiàn)。最后,函數(shù)又通過調(diào)用 ActivityThread 類的成員變量 mInstrumentation 所描述一個Instrumentation對象的成員函數(shù) callActivityOnCreate 來通知Activity 組件實(shí)例 activity,它已經(jīng)被創(chuàng)建和啟動起來了。在接下來的Step9中,我們再分析它的成員函數(shù)callActivityOnCreate的實(shí)現(xiàn)。接下來,我們就分別分析 Instrumentation 類的成員函數(shù)類的構(gòu)造函數(shù)以及成員函數(shù) setOuterContext、Activity 類的成員函數(shù)類的成員函數(shù) callActivityOnCreate 的實(shí)現(xiàn)。
newActivityattach和
、ContextImplInstrumentationStep2.Instrumentation.newActivity[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicclassInstrumentation{......publicActivitynewActivity(ClassLoadercl,StringclassName,Intentintent)throwsInstantiationException,IllegalAccessException,ClassNotFoundException{return(Activity)cl.loadClass(className).newInstance();}......}這個函數(shù)定義在文件 frameworks/base/core/java/android/app/Instrumentation.java 中。參數(shù)cl描述的是一個類加載器, 而參數(shù)className描述的要加載的類。以className為參數(shù)來調(diào)用 cl描述的是一個類加載器的成員函數(shù) loadClass,就可以得到一個 Class對象。由于className描述的是一個 Activity 子類,因此,當(dāng)函數(shù)調(diào)用前面得到的 Class對象的成員函數(shù)newInstance的時候,就會創(chuàng)建一個 Activity 子類實(shí)例。這個Activity 實(shí)例就是用來描述在前面 Step1中所要啟動的 Activity 組件的。Activity
子類實(shí)例在創(chuàng)建的過程,
會調(diào)用父類
Activity
的默認(rèn)構(gòu)造函數(shù), 以便可以完成Activity組件的創(chuàng)建過程。Step3.newActivityActivity 類定義在文件 frameworks/base/core/java/android/app/Activity.java 中,它沒有定義自己的構(gòu)造函數(shù),因此,系統(tǒng)就會為它提供一個默認(rèn)的構(gòu)造函數(shù)。 一般來說,一個類的構(gòu)造函數(shù)是用來初始化該類的實(shí)例的,但是, 系統(tǒng)為Activity 類提供的默認(rèn)構(gòu)造函數(shù)什么也不做,也就是說, Activity 類實(shí)例在創(chuàng)建的時候,還沒有執(zhí)行實(shí)質(zhì)的初始化工作。這個初始化工作要等到 Activity 類的成員函數(shù) attach被調(diào)用的時候才會執(zhí)行。在后面的 Step6中,我們就會看到 Activity 類的成員函數(shù) attach是如何初始化一個 Activity 類實(shí)例的。這一步執(zhí)行完成之后,回到前面的 Step1中,即performLaunchActivity 中,接下來就會調(diào)用 ContextImpl
ActivityThread類的成員函數(shù)類的構(gòu)造函數(shù)來創(chuàng)建一個ContextImpl
對象,以便可以用來描述正在啟動的
Activity
組件的運(yùn)行上下文信息。Step4.newContextImpl[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片classContextImplextendsContext{......privateContextmOuterContext;......ContextImpl(){Fordebugonly//++sInstanceCount;mOuterContext=this;}......}這個函數(shù)定義在文件frameworks/base/core/java/android/app/ContextImpl.java中。ContextImpl類的成員變量mOuterContext的類型為Context。當(dāng)一個ContextImpl對象是用來描述一個Activity組件的運(yùn)行上下文環(huán)境時,那么它的成員變量mOuterContext指向的就是該Activity組件。由于一個ContextImpl對象在創(chuàng)建的時候,并沒有參數(shù)用來指明它是用來描述一個Activity組件的運(yùn)行上下文環(huán)境,因此,這里就暫時將它的成員變量mOuterContext指向它自己。在接下來的Step5中,我們就會看到,一個ContextImpl對象所關(guān)聯(lián)的一個 Activity 組件是通過調(diào)用 ContextImpl類的成員函數(shù) setOuterContext來設(shè)置的。這一步執(zhí)行完成之后,回到前面的 Step1中,即 ActivityThread 類的成員函數(shù)performLaunchActivity 中,接下來就會調(diào)用 ContextImpl類的成員函數(shù) setOuterContext來設(shè)置前面所創(chuàng)建一個 ContextImpl對象所關(guān)聯(lián)的一個 Activity 組件,即正在啟動的 Activity 組件。Step5.ContextImpl.setOuterContext[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片classContextImplextendsContext{......privateContextmOuterContext;......finalvoidsetOuterContext(Contextcontext){mOuterContext=context;}......}這個函數(shù)定義在文件 frameworks/base/core/java/android/app/ContextImpl.java 中。參數(shù) context描述的是一個正在啟動的 Activity 組件,ContextImpl 類的成員函數(shù)setOuterContext只是簡單地將它保存在成員變量 mContext中,以表明當(dāng)前正在處理的一個ContextImpl對象是用來描述一個 Activity 組件的運(yùn)行上下文環(huán)境的。這一步執(zhí)行完成之后,回到前面的 Step1中,即 ActivityThread 類的成員函數(shù)performLaunchActivity 中,接下來就會調(diào)用 Activity 類的成員函數(shù) attach來初始化正在啟動的Activity 組件,其中,就包括設(shè)置正在啟動的 Activity 組件的運(yùn)行上下文環(huán)境。Step6.Activity.attach[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicclassActivityextendsContextThemeWrapperimplementsLayoutInflater.Factory,Window.Callback,KeyEvent.Callback,OnCreateContextMenuListener,ComponentCallbacks{......privateApplicationmApplication;....../*package*/ConfigurationmCurrentConfig;......privateWindowmWindow;privateWindowManagermWindowManager;......finalvoidattach(Contextcontext,ActivityThreadaThread,Instrumentationinstr,IBindertoken,intident,Applicationapplication,Intentintent,ActivityInfoinfo,CharSequencetitle,Activityparent,Stringid,ObjectlastNonConfigurationInstance,HashMap<String,Object>lastNonConfigurationChildInstances,Configurationconfig){attachBaseContext(context);mWindow=PolicyManager.makeNewWindow(this);mWindow.setCallback(this);mWindow.setSoftInputMode(info.softInputMode);}......mApplication=application;......mWindow.setWindowManager(null,mToken,mComponent.flattenToString());......mWindowManager=mWindow.getWindowManager();mCurrentConfig=config;}......}這個函數(shù)定義在文件 frameworks/base/core/java/android/app/Activity.java 中。函數(shù)首先調(diào)用從父類 ContextThemeWrapper繼承下來的成員函數(shù) attachBaseConext來設(shè)置運(yùn)行上下文環(huán)境,即將參數(shù)context所描述的一個ContextImpl對象保存在內(nèi)部。在接下來的Step7中,我們再分析ContextThemeWrapper類的成員函數(shù)attachBaseConext的實(shí)現(xiàn)。函數(shù)接下來調(diào)用PolicyManager類的靜態(tài)成員函數(shù)makeNewWindow來創(chuàng)建了一個PhoneWindow,并且保存在Activity類的成員變量mWindow中。這個PhoneWindow是用來描述當(dāng)前正在啟動的應(yīng)用程序窗口的。 這個應(yīng)用程序窗口在運(yùn)行的過程中, 會接收到一些事件,例如,鍵盤、觸摸屏事件等,這些事件需要轉(zhuǎn)發(fā)給與它所關(guān)聯(lián)的 Activity 組件處理,這個轉(zhuǎn)發(fā)操作是通過一個 Window.Callback 接口來實(shí)現(xiàn)的。由于 Activity 類實(shí)現(xiàn)了Window.CallbackWindow.Callback
接口,因此,函數(shù)就可以將當(dāng)前正在啟動的接口設(shè)置到前面創(chuàng)建的一個 PhoneWindow
Activity 組件所實(shí)現(xiàn)的一個里面去,這是通過調(diào)用 Window類的成員函數(shù) setCallback來實(shí)現(xiàn)的。參數(shù)info指向的是一個ActivityInfo對象,用來描述當(dāng)前正在啟動的Activity組件的信息。其中,這個ActivityInfo對象的成員變量softInputMode用來描述當(dāng)前正在啟動的一個Activity組件是否接受軟鍵盤輸入。如果接受的話,那么它的值就不等于,并且描述的是當(dāng)前正在啟動的Activity 組件所接受的軟鍵盤輸入模式。一個PhoneWindow對象內(nèi)部去,這是通過調(diào)用現(xiàn)的。
這個軟鍵盤輸入模式設(shè)置到前面所創(chuàng)建的Window類的成員函數(shù) setSoftInputMode
來實(shí)在Android系統(tǒng)中,每一個應(yīng)用程序窗口都需要由一個窗口管理者來管理,因此,函數(shù)再接下來就會調(diào)用前面所創(chuàng)建的一個PhoneWindow對象從父類Window繼承下來的成員函數(shù)setWindowManager來為它設(shè)置一個合適的窗口管理者。這個窗口管理者設(shè)置完成之后,就可以通過調(diào)用Window類的成員函數(shù)getWindowManager來獲得。獲得這個窗口管理者之后,函數(shù)就將它保存在Activity類的成員變量mWindowManager中。這樣,當(dāng)前正在啟動的Activity組件以后就可以通過它的成員變量mWindowManager來管理與它所關(guān)聯(lián)的窗口。除了創(chuàng)建和初始化一個 PhoneWindow之外,函數(shù)還會分別把參數(shù) application和config所描述的一個 Application 對象和一個 Configuration 對象保存在mApplication和mCurrentConfig中。這樣,當(dāng)前正在啟動的 Activity用程序信息以及配置信息。
Activity類的成員變量組件就可以訪問它的應(yīng)在接下來的一篇文章中,我們再詳細(xì)分析 PolicyManagermakeNewWindow,以及 Window 類的成員函數(shù) setCallback、setWindowManager的實(shí)現(xiàn),以便可以了解應(yīng)用程序窗口的創(chuàng)建過程。
類的靜態(tài)成員函數(shù)setSoftInputMode 和接下來,我們繼續(xù)分析
ContextThemeWrapper
類的成員函數(shù)
attachBaseConext的實(shí)現(xiàn),以便可以繼續(xù)了解一個應(yīng)用程序窗口的運(yùn)行上下文環(huán)境的設(shè)置過程。Step7.ContextThemeWrapper.attachBaseConext[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicclassContextThemeWrapperextendsContextWrapper{......@OverrideprotectedvoidattachBaseContext(ContextnewBase){super.attachBaseContext(newBase);mBase=newBase;}......}這 個 函 數(shù) 定 義 在 文 件frameworks/base/core/java/android/view/ContextThemeWrapper.java 中。ContextThemeWrapper類用來維護(hù)一個應(yīng)用程序窗口的主題,而用來描述這個應(yīng)用程序窗口的運(yùn)行上下文環(huán)境的一個ContextImpl對象就保存在ContextThemeWrapper類的成員函數(shù)mBase中。ContextThemeWrapper類的成員函數(shù) attachBaseConext的實(shí)現(xiàn)很簡單,它首先調(diào)用父類 ContextWrapper 的成員函數(shù) attachBaseConext來將參數(shù)ContextImpl 對象保存到父類 ContextWrapper中去,接著再將這個ContextThemeWrapper類的成員變量 mBase中。
newBase所描述的一個ContextImpl 對象保存在接下來,我們就繼續(xù)分析
ContextWrapper
類的成員函數(shù)
attachBaseConext的實(shí)現(xiàn)。Step8.ContextWrapper.attachBaseConext[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicclassContextWrapperextendsContext{ContextmBase;......protectedvoidattachBaseContext(Contextbase){if(mBase!=null){thrownewIllegalStateException("Basecontextalreadyset");}mBase=base;}......}這個函數(shù)定義在文件 frameworks/base/core/java/android/content/ContextWrapper.java中。ContextWrapper類只是一個代理類,它只是簡單地封裝了對其成員變量 mBase所描述的一個Context對象的操作。ContextWrapper類的成員函數(shù)attachBaseConext的實(shí)現(xiàn)很簡單,它只是將參數(shù)base所描述的一個ContextImpl對象保存在成員變量mBase中。這樣,ContextWrapper
類就可以將它的功能交給
ContextImpl
類來具體實(shí)現(xiàn)。這一步執(zhí)行完成之后,當(dāng)前正在啟動的Activity組件的運(yùn)行上下文環(huán)境就設(shè)置完成了,回到前面的Step1中,即ActivityThread類的成員函數(shù)performLaunchActivity中,接下來就會調(diào)用Instrumentation類的成員函數(shù)callActivityOnCreate來通知當(dāng)前正在啟動的Activity 組件,它已經(jīng)創(chuàng)建和啟動完成了。Step9.Instrumentation.callActivityOnCreate[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicclassInstrumentation{......publicvoidcallActivityOnCreate(Activityactivity,Bundleicicle){......activity.onCreate(icicle);......}......}這個函數(shù)定義在文件 frameworks/base/core/java/android/app/Instrumentation.java 中。函數(shù)主要就是調(diào)用當(dāng)前正在啟動的Activity組件的成員函數(shù)onCreate,用來通知它已經(jīng)成功地創(chuàng)建和啟動完成了。Step10.Activity.onCreate[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicclassActivityextendsContextThemeWrapperimplementsLayoutInflater.Factory,Window.Callback,KeyEvent.Callback,OnCreateContextMenuListener,ComponentCallbacks{......booleanmCalled;....../*package*/booleanmVisibleFromClient=true;......protectedvoidonCreate(BundlesavedInstanceState){mVisibleFromClient=!mWindow.getWindowStyle().getBoolean(}......}這個函數(shù)定義在文件 frameworks/base/core/java/a
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 【正版授權(quán)】 ISO/ASTM TS 52949:2025 EN Additive manufacturing of metals - Qualification principles - Installation,operation and performance (IQ/OQ/PQ) of PBF-EB equipment
- 2024年秋季藝術(shù)品展銷會交易合同3篇
- 2024年私人房屋租賃管理服務(wù)合同3篇
- 笨氯苯課程設(shè)計文獻(xiàn)
- 游學(xué)課程設(shè)計培訓(xùn)總結(jié)
- 甜點(diǎn)面包烘焙 課程設(shè)計
- 環(huán)保課程設(shè)計理念有哪些
- 醫(yī)院醫(yī)療質(zhì)量安全管理制度與規(guī)范
- 研學(xué)課程設(shè)計國風(fēng)藝術(shù)
- 粽子醬的制作課程設(shè)計
- 教代會會場背景(紅旗)圖片課件
- 腦出血護(hù)理查房-中醫(yī)院
- 森林生態(tài)系統(tǒng)固碳現(xiàn)狀、速率、機(jī)制和潛力研究實(shí)施方案細(xì)則
- 公眾責(zé)任保險知識培訓(xùn)教育課件
- 深基坑事故案例
- 中國茶文化(中文版)
- 02J401鋼梯安裝圖集
- 川省成都市2022屆高二上學(xué)期期末考試:英語
- 人教版小學(xué)三年級語文上冊第三單元集體備課活動記錄
- 消防安全操作規(guī)程
- 水利水電工程危險源辨識與風(fēng)險評價一覽表
評論
0/150
提交評論