Android Context類結構詳解
大家好, 今天給大家介紹下我們在應用開發中最熟悉而陌生的朋友-----Context類 ,說它熟悉,是應為我們在開發中
時刻的在與它打交道,例如:Service、BroadcastReceiver、Activity等都會利用到Context的相關方法 ; 說它陌生,完全是
因為我們真正的不懂Context的原理、類結構關係。一個簡單的問題是,一個應用程式App中存在多少個Context例項物件呢?
一個、兩個? 在此先賣個關子吧。讀了本文,相信您會豁然開朗的 。
Context,中文直譯為“上下文”,SDK中對其說明如下:
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
從上可知一下三點,即:
1、它描述的是一個應用程式環境的資訊,即上下文。
2、該類是一個抽象(abstract class)類,Android提供了該抽象類的具體實現類(後面我們會講到是ContextIml類)。
3、通過它我們可以獲取應用程式的資源和類,也包括一些應用級別操作,例如:啟動一個Activity,傳送廣播,接受Intent
資訊 等。。
於是,我們可以利用該Context物件去構建應用級別操作(application-level operations) 。
一、Context相關類的繼承關係
很多人看類圖或者程式碼肯定覺得很混亂,不知道ContextImp和ContextWrapper到底是什麼關係,其實如果你瞭解裝飾者(Decorator)設計模式的話就很簡單了,不瞭解的可以去看一下。
相關類介紹:
Context類 路徑: /frameworks/base/core/java/android/content/Context.java
說明: 抽象類,提供了一組通用的API。
原始碼(部分)如下:
[java] view plaincopyprint?- publicabstractclass Context {
- ...
- publicabstract Object getSystemService(String name); //獲得系統級服務
- publicabstractvoid startActivity(Intent intent); //通過一個Intent啟動Activity
- publicabstract ComponentName startService(Intent service); //啟動Service
- //根據檔名得到SharedPreferences物件
- publicabstract SharedPreferences getSharedPreferences(String name,int mode);
- ...
- }
ContextIml.java類 路徑 :/frameworks/base/core/java/android/app/ContextImpl.java
說明:該Context類的實現類為ContextIml,該類實現了Context類的功能。請注意,該函式的大部分功能都是直接呼叫
其屬性mPackageInfo去完成,這點我們後面會講到。
原始碼(部分)如下:
[java] view plaincopyprint?- /**
- * Common implementation of Context API, which provides the base
- * context object for Activity and other application components.
- */
- class ContextImpl extends Context{
- //所有Application程式公用一個mPackageInfo物件
- /*package*/ LoadedApk mPackageInfo;
- @Override
- public Object getSystemService(String name){
- ...
- elseif (ACTIVITY_SERVICE.equals(name)) {
- return getActivityManager();
- }
- elseif (INPUT_METHOD_SERVICE.equals(name)) {
- return InputMethodManager.getInstance(this);
- }
- }
- @Override
- publicvoid startActivity(Intent intent) {
- ...
- //開始啟動一個Activity
- mMainThread.getInstrumentation().execStartActivity(
- getOuterContext(), mMainThread.getApplicationThread(), null, null, intent, -1);
- }
- }
ContextWrapper類 路徑 :\frameworks\base\core\java\android\content\ContextWrapper.java
說明: 正如其名稱一樣,該類只是對Context類的一種包裝,該類的建構函式包含了一個真正的Context引用,即ContextIml
物件。 原始碼(部分)如下:
[java] view plaincopyprint?- publicclass ContextWrapper extends Context {
- Context mBase; //該屬性指向一個ContextIml例項,一般在建立Application、Service、Activity時賦值
- //建立Application、Service、Activity,會呼叫該方法給mBase屬性賦值
- protectedvoid attachBaseContext(Context base) {
- if (mBase != null) {
- thrownew IllegalStateException("Base context already set");
- }
- mBase = base;
- }
- @Override
- publicvoid startActivity(Intent intent) {
- mBase.startActivity(intent); //呼叫mBase例項方法
- }
- }
ContextThemeWrapper類 路徑:/frameworks/base/core/java/android/view/ContextThemeWrapper.java
說明:該類內部包含了主題(Theme)相關的介面,即android:theme屬性指定的。只有Activity需要主題,Service不需要主題,
所以Service直接繼承於ContextWrapper類。
原始碼(部分)如下:
[java] view plaincopyprint?- publicclass ContextThemeWrapper extends ContextWrapper {
- //該屬性指向一個ContextIml例項,一般在建立Application、Service、Activity時賦值
- private Context mBase;
- //mBase賦值方式同樣有一下兩種
- public ContextThemeWrapper(Context base, int themeres) {
- super(base);
- mBase = base;
- mThemeResource = themeres;
- }
- @Override
- protectedvoid attachBaseContext(Context newBase) {
- super.attachBaseContext(newBase);
- mBase = newBase;
- }
- }
Activity類 、Service類 、Application類本質上都是Context子類, 更多資訊大家可以自行參考原始碼進行理解。
二、 什麼時候建立Context例項
熟悉了Context的繼承關係後,我們接下來分析應用程式在什麼情況需要建立Context物件的?應用程式建立Context例項的
情況有如下幾種情況:
1、建立Application 物件時, 而且整個App共一個Application物件
2、建立Service物件時
3、建立Activity物件時
因此應用程式App共有的Context數目公式為:
總Context例項個數 = Service個數 + Activity個數 + 1(Application對應的Context例項)
具體建立Context的時機
1、建立Application物件的時機
每個應用程式在第一次啟動時,都會首先建立Application物件。如果對應用程式啟動一個Activity(startActivity)流程比較
清楚的話,建立Application的時機在建立handleBindApplication()方法中,該函式位於 ActivityThread.java類中 ,如下:
[java] view plaincopyprint?- //建立Application時同時建立的ContextIml例項
- privatefinalvoid handleBindApplication(AppBindData data){
- ...
- ///建立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(); //建立一個ContextImpl物件例項
- appContext.init(this, null, mActivityThread); //初始化該ContextIml例項的相關屬性
- ///新建一個Application物件
- app = mActivityThread.mInstrumentation.newApplication(
- cl, appClass, appContext);
- appContext.setOuterContext(app); //將該Application例項傳遞給該ContextImpl例項
- }
- ...
- }
2、建立Activity物件的時機
通過startActivity()或startActivityForResult()請求啟動一個Activity時,如果系統檢測需要新建一個Activity物件時,就會
回撥handleLaunchActivity()方法,該方法繼而呼叫performLaunchActivity()方法,去建立一個Activity例項,並且回撥
onCreate(),onStart()方法等, 函式都位於 ActivityThread.java類 ,如下:
[java] view plaincopyprint?- //建立一個Activity例項時同時建立ContextIml例項
- privatefinalvoid handleLaunchActivity(ActivityRecord r, Intent customIntent) {
- ...
- Activity a = performLaunchActivity(r, customIntent); //啟動一個Activity
- }
- privatefinal Activity performLaunchActivity(ActivityRecord r, Intent customIntent) {
- ...
- Activity activity = null;
- try {
- //建立一個Activity物件例項
- java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
- activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
- }
-
if (activity != null
相關推薦
Android Context類結構詳解
大家好, 今天給大家介紹下我們在應用開發中最熟悉而陌生的朋友-----Context類 ,說它熟悉,是應為我們在開發中 時刻的在與它打交道,例如:Service、BroadcastReceiver、Activity等都會利用到Context的相關方法 ; 說它陌
Android原始碼目錄結構詳解
轉自:http://blog.csdn.net/xiangjai/article/details/9012387 在學習Android的過程中,學習寫應用還好,一開始不用管太多程式碼,直接呼叫函式就可以了,但是工作中卻需要修改到framework之類的東東 所以感覺開始糾結了,又是
Android file類使用詳解-SDcard
Android file類使用詳解 一.Android file類 在開發Android應用時免不了會跟檔案打交道,本篇文章記錄總結自己常用到的檔案操作,資料的儲存有多種方式,比如資料庫儲存、
最全的Android原始碼目錄結構詳解
android平臺四層架構對應原始碼中的目錄: 第一層:應用程式層(applications)對應根目錄下packages/apps 第二層:應用程式框架層(application framework)對應根目錄下的frameworks 第三層:執行庫
Android OS體系結構詳解
Google於2007年11月5日宣佈的基於Linux平臺的開源手機作業系統的名稱,該平臺由作業系統、中介軟體、使用者介面和應用軟體組成,號稱是首個為移動終端打造的真正開放和完整的移動軟體。 架構詳解 下面自底向上分析各層:1、Linux Kernel Andro
android context獲取目錄詳解
獲取 sqlite系統資料庫路徑 方式1: ApkInfo apkInfo = new ResourceUtil(context).getApkInfo();APP_PATH = new StringBuilder("/data/data/").append(apkInfo
Java類文件結構詳解
nature default 層次 size 原理 etc 識別 格式 def 概述: Class文件結構是了解虛擬機的重要基礎之一,如果想深入的了解虛擬機,Class文件結構是不能不了解的。Class文件是一組以8位字節為基礎單位的二進制流,各項數據項目嚴格按照順序緊湊
Android 8原始碼目錄結構詳解
|- art // Android Runtime,一種App執行模式,區別於傳統的Dalvik虛擬機器,旨在提高Android系統的流暢性,包括以下目錄 |- benchmark // 程式測試基準。 |-
Android Studio 外掛開發詳解二:工具類
轉載請標明出處:http://blog.csdn.net/zhaoyanjun6/article/details/78112856 本文出自【趙彥軍的部落格】 在外掛開發過程中,我們按照開發一個正式的專案來操作,需要整理一些常用工具類。 Http 請求封裝 在外掛的專案中,我們看到依賴庫如下圖所示:
Android原始碼hardware目錄結構詳解
hardware 目錄 (部分廠家開源的硬解適配層HAL程式碼) |-- broadcom (博通公司) | `-- wlan (無線網絡卡) |-
Android的Looper類使用詳解
1. Looper類用來為一個執行緒開啟一個訊息迴圈。 預設情況下android中新誕生的執行緒是沒有開啟訊息迴圈的。(主執行緒除外,主執行緒系統會自動為其建立Looper物件,開啟訊息迴圈。) Looper物件通過MessageQueue來存放訊息和事件。
Android 工具之系統五層框架體系結構詳解
從下圖中可以很清楚得看出,整個架構可以分為五大層次: System Apps:即系統應用層,這一層中都是我們使用手機時都會直接接觸到的各種應用。 Java API Framework:即 Java 介面框架層,這一層是為了上層應用提供各種介面。 Native C/C
Android專案檔案及應用程式—目錄結構詳解
今天要介紹的就是android的目錄結構,在建立新專案的過程中,ADT會自動建立一些目錄和檔案,這些目錄和檔案有其固定的作用,有的允許修改,有的不能修改。一個新建立的Android專案,專案結構包含src目錄、gen目錄、assets目錄、res目錄、庫檔案android.jar、以及三個專案工程檔案
Java資料結構和算法系列3--ThreadLocal類原理詳解
1.ThreadLocal介紹 Java實現多執行緒的2種方式,繼承Thread類和實現Runnable介面。今天我們介紹下另外一種常用的多執行緒類ThreadLocal類。 ThreadLocal在維護變數時,為每個使用變數的執行緒提供了獨立的副本,所以每
Android系統四層體系結構詳解
開門見山,先上圖 很明顯四層:接下來一一講解: Java應用程式層: Android會同一系列核心應用程式包一起釋出,該應用程式包包括客戶端,SMS短訊息程式,日曆,地圖,瀏覽器,聯絡人管理程式等。所有的應用程式都是使用JAVA語言編寫的。
Android專案原始碼架包結構詳解
1、專案開始後建工程,良好的架包習慣可以體現一個專案的優秀程度,所以發表一篇文章來談談如何做好架包問題,本人因為專案原因做了一個簡單的架包,望各位大牛們吐槽,如下: 這就是一個簡單工
Buffer類的詳解(轉)
iteye 原始數據類型 pub bst exception 如何 數字 硬件 final Buffer 類是 java.nio 的構造基礎。一個 Buffer 對象是固定數量的數據的容器,其作用是一個存儲器,或者分段運輸區,在這裏,數據可被存儲並在之後用於檢索。緩沖區可以
[轉載]AMOLED結構詳解,BOE專家給你分析驅動補償
晶體 即使 長時間 http 如何 電容 環境 抽取 分享 關鍵詞: AMOLED, 驅動補償 有機發光顯示二極管(OLED)作為一種電流型發光器件已越來越多地被應用於高性能顯示中。由於它自發光的特性,與LCD相比,AMOLED具有高對比度、超輕薄
[轉]C#進階系列——WebApi 接口返回值不困惑:返回值類型詳解
try 接口測試工具 des rep home creat port 調用 學習 本文轉自:http://www.cnblogs.com/landeanfen/p/5501487.html 閱讀目錄 一、void無返回值 二、IHttpActionResult
JS函數動作分層結構詳解及Document.getElementById 釋義 事件 函數 變量 script標簽 var function
src 分層 鼠標 靜態頁面 font 編寫 技術分享 對話 fun html +css 靜態頁面 js 動態 交互 原理: js就是修改樣式, 比如彈出一個對話框. 彈出的過程就是這個框由disable 變成display:enable. 又或者當鼠標指