1. 程式人生 > >Android Context類結構詳解

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?
  1. publicabstractclass Context {  
  2.      ...  
  3.      publicabstract Object getSystemService(String name);  //獲得系統級服務
  4.      publicabstractvoid startActivity(Intent intent);     //通過一個Intent啟動Activity
  5.      publicabstract ComponentName startService(Intent service);  //啟動Service
  6.      //根據檔名得到SharedPreferences物件
  7.      publicabstract SharedPreferences getSharedPreferences(String name,int mode);  
  8.      ...  
  9. }  

  ContextIml.java類  路徑 :/frameworks/base/core/java/android/app/ContextImpl.java

          說明:該Context類的實現類為ContextIml,該類實現了Context類的功能。請注意,該函式的大部分功能都是直接呼叫

      其屬性mPackageInfo去完成,這點我們後面會講到。    

         原始碼(部分)如下:

[java] view plaincopyprint?
  1. /** 
  2.  * Common implementation of Context API, which provides the base 
  3.  * context object for Activity and other application components. 
  4.  */
  5. class ContextImpl extends Context{  
  6.     //所有Application程式公用一個mPackageInfo物件
  7.     /*package*/ LoadedApk mPackageInfo;  
  8.     @Override
  9.     public Object getSystemService(String name){  
  10.         ...  
  11.         elseif (ACTIVITY_SERVICE.equals(name)) {  
  12.             return getActivityManager();  
  13.         }   
  14.         elseif (INPUT_METHOD_SERVICE.equals(name)) {  
  15.             return InputMethodManager.getInstance(this);  
  16.         }  
  17.     }   
  18.     @Override
  19.     publicvoid startActivity(Intent intent) {  
  20.         ...  
  21.         //開始啟動一個Activity
  22.         mMainThread.getInstrumentation().execStartActivity(  
  23.             getOuterContext(), mMainThread.getApplicationThread(), nullnull, intent, -1);  
  24.     }  
  25. }  

ContextWrapper類 路徑 :\frameworks\base\core\java\android\content\ContextWrapper.java

        說明: 正如其名稱一樣,該類只是對Context類的一種包裝,該類的建構函式包含了一個真正的Context引用,即ContextIml

       物件。    原始碼(部分)如下:

[java] view plaincopyprint?
  1. publicclass ContextWrapper extends Context {  
  2.     Context mBase;  //該屬性指向一個ContextIml例項,一般在建立Application、Service、Activity時賦值
  3.     //建立Application、Service、Activity,會呼叫該方法給mBase屬性賦值
  4.     protectedvoid attachBaseContext(Context base) {  
  5.         if (mBase != null) {  
  6.             thrownew IllegalStateException("Base context already set");  
  7.         }  
  8.         mBase = base;  
  9.     }  
  10.     @Override
  11.     publicvoid startActivity(Intent intent) {  
  12.         mBase.startActivity(intent);  //呼叫mBase例項方法
  13.     }  
  14. }  

   ContextThemeWrapper類 路徑:/frameworks/base/core/java/android/view/ContextThemeWrapper.java

      說明:該類內部包含了主題(Theme)相關的介面,即android:theme屬性指定的。只有Activity需要主題,Service不需要主題,

   所以Service直接繼承於ContextWrapper類。

      原始碼(部分)如下:

[java] view plaincopyprint?
  1. publicclass ContextThemeWrapper extends ContextWrapper {  
  2.      //該屬性指向一個ContextIml例項,一般在建立Application、Service、Activity時賦值
  3.      private Context mBase;  
  4.     //mBase賦值方式同樣有一下兩種
  5.      public ContextThemeWrapper(Context base, int themeres) {  
  6.             super(base);  
  7.             mBase = base;  
  8.             mThemeResource = themeres;  
  9.      }  
  10.      @Override
  11.      protectedvoid attachBaseContext(Context newBase) {  
  12.             super.attachBaseContext(newBase);  
  13.             mBase = newBase;  
  14.      }  
  15. }  

     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?
  1. //建立Application時同時建立的ContextIml例項
  2. privatefinalvoid handleBindApplication(AppBindData data){  
  3.     ...  
  4.     ///建立Application物件
  5.     Application app = data.info.makeApplication(data.restrictedBackupMode, null);  
  6.     ...  
  7. }  
  8. public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {  
  9.     ...  
  10.     try {  
  11.         java.lang.ClassLoader cl = getClassLoader();  
  12.         ContextImpl appContext = new ContextImpl();    //建立一個ContextImpl物件例項
  13.         appContext.init(thisnull, mActivityThread);  //初始化該ContextIml例項的相關屬性
  14.         ///新建一個Application物件 
  15.         app = mActivityThread.mInstrumentation.newApplication(  
  16.                 cl, appClass, appContext);  
  17.        appContext.setOuterContext(app);  //將該Application例項傳遞給該ContextImpl例項         
  18.     }   
  19.     ...  
  20. }  

    2、建立Activity物件的時機

       通過startActivity()或startActivityForResult()請求啟動一個Activity時,如果系統檢測需要新建一個Activity物件時,就會

  回撥handleLaunchActivity()方法,該方法繼而呼叫performLaunchActivity()方法,去建立一個Activity例項,並且回撥

 onCreate(),onStart()方法等, 函式都位於 ActivityThread.java類 ,如下:

[java] view plaincopyprint?
  1. //建立一個Activity例項時同時建立ContextIml例項
  2. privatefinalvoid handleLaunchActivity(ActivityRecord r, Intent customIntent) {  
  3.     ...  
  4.     Activity a = performLaunchActivity(r, customIntent);  //啟動一個Activity
  5. }  
  6. privatefinal Activity performLaunchActivity(ActivityRecord r, Intent customIntent) {  
  7.     ...  
  8.     Activity activity = null;  
  9.     try {  
  10.         //建立一個Activity物件例項
  11.         java.lang.ClassLoader cl = r.packageInfo.getClassLoader();  
  12.         activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);  
  13.     }  
  14.     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. 又或者當鼠標指