Android Context 到底是什麼?
什麼是Context?
一個Context意味著一個場景,一個場景就是我們和軟體進行互動的一個過程。比如當你使用微信的時候,場景包括聊天介面、通訊錄、朋友圈,以及背後的一些資料。
那麼從程式的角度來看,Context是什麼?其實一個Activity就是一個Context,一個Service也是一個Context。
一個應用程式可以認為是一個工作環境,使用者在這個工作環境中會切換到不同的場景,這就像一個助理,他可能需要接待客人,可能還要列印檔案,還可能接聽電話,而這些就稱之為不同的場景,助理可稱之為一個應用程式。
Activity類的確是基於Context,而Service類也是基於Context。Activity除了基於Context類外,還實現了一些其他重要的介面,從架構設計的角度看,interface僅僅是某些功能,而extends才是類的本質,即Activity的本質是一個Context,其所實現的其他介面只是為了擴充Context的功能而已,擴充後的類稱之為一個Activity或Service。
一個應用程式中應該有多少個Context物件
我們在應用程式開發中經常會呼叫Context的一些方法,這些方法看起來似乎會返回一些全域性的物件,而不僅僅是某個Activity,可能會有點疑問,一個應用程式到底有多少個Context物件呢?比如,Context.getResources()返回該應用程式所對應的Resource類物件,無論從哪個Activity中呼叫,都會返回同一個Resource物件。
- 一個Activity就是一個場景(Context),一個Service也是一個場景,所以,應用程式中有多少個Activity或者Service就會有多少個Context物件。
- getResource()等方法返回的是同一個全域性物件。
Context 相關類是怎麼繼承的呢?
Context類本身是一個純abstract類。為了使用方便又定義了Context包裝類-ContextWrapper,ContextWrapper建構函式中必須包含一個真正的Context引用,同時ContextWrapper中有attachBaseContext()用於給ContextWrapper物件中指定真正的Context物件。
ContextThemeWrapper內部包含了與主題相關的介面,這裡的主題就是指在AndroidManifest.xml中通過Android:theme為Application或者Activity指定的主題。
只有Activity才需要主題,Service不需要主題的,所以Service直接繼承與ContextWrapper。
ContextImpl類真正實現了Context中所有的函式,我們所呼叫的各種Context類的方法其實實現均來自於該類。
什麼時候建立Context?
每一個應用程式在客戶端都是從ActivityThread類開始的,建立Context物件也是在該類中完成,具體建立ContextImpl類的地方一共有6處:
- PackageInfo.makeApplication()
- performLaunchActivity()
- handleCreateBackupAgent()
- handleCreateService()
- handleBindApplication()
- attach()
其中attach()方法僅在Framework程式啟動時呼叫,應用程式執行時不會呼叫到該方法。
Application對應的Context
程式第一次啟動時,會輾轉呼叫到makeApplication()方法。具體程式碼如下:
ContextImpl appContext = new ContextImpl(); appContext.init(this,null,mActivityThread); .... appContext.setOuterContext(app);
Activity對應的Context
啟動Activity時,Ams會通過IPC呼叫到ActivityThread的scheduleLaunchActivity()方法,該方法包含兩種引數。一種是ActivityInfo,這是一個實現了Parcelable介面的資料類,意味著該物件是Ams建立的,並通過IPC傳遞到ActivityThread;另一種是其他的一些引數。
scheduleLaunchActivity()方法中會根據以上兩種引數構造一個本地ActivityRecord資料類,ActivityThread內部會為每一個Activity建立一個ActivityRecord物件,並使用這些資料物件來管理Activity。
然後會呼叫handleLaunchActivity(),再呼叫performLaunchActivity(),該方法中建立ContextImpl的程式碼如下:
ContextImpl appContext = new ContextImpl(); appContext.init(r.packageInfo,r.token,this); appContext.setOuterContext(activity);
在performLaunchActivity()開始執行時,會為r.packageInfo變數賦值。r.packageInfo物件的PackageInfo物件和Application對應的packageInfo物件是同一個。
Service對應的Context
啟動Service時,Ams會通過IPC呼叫到ActivityThread的scheduleCreateService()方法,該方法也包含兩種引數。第一種是ServiceInfo,這是實現了一個Parcelable介面的資料類,該物件由AmS建立,並通過IPC傳遞到ActivityThread內部;第二種是其他引數。
在scheduleCreateService()方法中,會使用以上兩種引數構造一個CreateServiceData的資料物件,ActivityThread會為其所包含的每一個Service建立該資料物件,並通過這些物件來管理Service。
然後在執行handleCreateService()方法,建立ContextImpl物件程式碼如下:
ContextImpl appContext = new ContextImpl(); appContext.init(packageInfo,null,this); ... appContext.setOuterContext(service);
Service對應的Context物件內部的mPackageInfo與Activity、Application中是完全相同的。
這幾個Context之間的關係
從以上可以看出,建立Context物件的過程基本上是相同的,不同的僅僅是針對Application、Activity、Service使用了不同的資料物件。
一個應用程式包含的Context個數應該為:Context個數 = Service個數+Activity個數+1,最後的1是Application類本身也會對應一個Context物件。
應用程式中包含多個ContextImpl物件,而內部變數mPackageInfo卻指向同一個PackageInfo物件,這種設計結構一般意味著ContextImpl是一種輕量級類,而PackageInfo是一個重量級類。事實上確實是這樣,ContextImpl中的大多數進行包操作的重量級函式實際上都是轉向了mPackageInfo物件相應的方法,也就是事實上呼叫了同一個PackageInfo物件。
相關文章
- Android:JNI 與 NDK到底是什麼?Android
- 機器學習到底是什麼?機器學習
- ? babel到底是什麼❓Babel
- 理解DOM到底是什麼
- Java到底是什麼呢Java
- Spring Aware 到底是什麼?Spring
- 件斷點到底是什麼?斷點
- 區塊鏈到底是什麼區塊鏈
- Spring IoC 到底是什麼Spring
- 閉包函式到底是什麼?有什麼用?函式
- Java到底是什麼?學習java可以做什麼呢?Java
- Python到底是什麼?為什麼要學Python?Python
- Golang context (上下文)是什麼GolangContext
- 區塊鏈EOS到底是什麼?區塊鏈
- RDD到底是什麼?RDD的APIAPI
- 大資料到底是什麼鬼大資料
- 企業架構到底是什麼?架構
- 為什麼range不是迭代器?range到底是什麼型別?型別
- 【一探究竟】Flutter到底是什麼?Flutter
- __name__ == '__main__' 到底是什麼意思AI
- Spark RPC 到底是個什麼鬼?SparkRPC
- 事件迴圈Event loop到底是什麼事件OOP
- JS中裝飾器到底是什麼?JS
- SQLSERVER 阻塞之 PFS 頁到底是什麼?SQLServer
- 自動化框架到底是什麼?框架
- 阿里雲到底是幹什麼的阿里
- JS 的 new 到底是幹什麼的?JS
- 國外遊戲文案到底是幹什麼的?遊戲
- SRE工程師到底是做什麼的?工程師
- 【入門必看】比特幣到底是什麼?比特幣
- Python 中的數字到底是什麼?Python
- 資料分析到底是什麼?_光點科技
- 火熱的低程式碼到底是什麼?
- VoNR來了,它到底是什麼技術?
- 阿里雲到底是做什麼的呢?阿里
- SQL Server 中的 NOLOCK 到底是什麼意思?SQLServer
- [Java] 變數裡存的到底是什麼Java變數
- 大資料到底是幹什麼用的?大資料