2012-08-22 35 views
10

我只是出於興趣考慮Android sources。我發現的是,Context是一個抽象類的抽象方法:調用getApplicationContext()時調用的代碼在哪裏?

public abstract Context getApplicationContext(); 

ContextWrapper.java延伸Context.java這導致實現getApplicationContext()方法:

@Override 
    public Context getApplicationContext() { 
     return mBase.getApplicationContext(); 
    } 

mBase是參考Context類型的對象其初始化於ContextWrapper的構造函數:

public ContextWrapper(Context base) { 
    mBase = base; 
} 

那麼這個mBase參考是指abstract類? 嗯,我只是不明白你從Activity撥打getApplicationContext()時執行的代碼在哪裏。

+0

你理解類是如何抽象的工作?有一些具體的類可以擴展Context,這就是實現方法的地方。 –

+0

我對它的感興趣,我理解抽象類是如何工作的。 – Eugene

回答

15

這是一個多態性的有趣例子。

只要你base擴展Context,它提供的getApplicationContext()的實現,這在ContextWrapper的情況是,你在這裏提供的代碼。有這個實現,並且the one in ContextImpl

重要的是要注意的幾件事情是很重要的閱讀您所提供的代碼時:ContextWrapper本身延伸Context,但它也需要一個Context爲輸入(這可能是一個ContextWrapper,或ServiceApplication,或Activity)。 ContextWrapper不在乎它是哪種類型;它只是知道他們有一個方法getApplicationContext,它想要在調用時調用該方法。 (例如,它可以通過另一種ContextWrapper,但因爲說ContextWrapper也需要在其構造Context,將只需添加嵌套的另一個層次。)

Application extends ContextWrapper類調​​用super(null),這將意味着getApplicationContext()會如果它被留下那麼扔NullPointerException - 但是,在ContextWrapper它也可以由attachBaseContext(Context)設置,這就是它變得有趣的地方。

ActivityApplication都有方法attach(Context [...other stuff])。他們每個人撥打attachBaseContext()與傳入Context

  • Instrumentation類,你會發現android.app.Instrumentation.newApplication(),其中ContextImpl創建,並傳遞到Application
  • ActivityThread課程中,您會發現handleBindApplication,它會創建一個ContextImpl,作爲其根Context傳遞給Activity
  • LoadedApk課程中,您會發現makeApplication,它會創建一個傳遞到ApplicationContextImplHere是它被稱爲的地方。

因此,在一天結束時,mBase通常結束爲ContextImpl

潛在有用的鏈接我看了一下,同時尋找這一切了:

+0

謝謝你的回答,喬恩。我很困惑,因爲在Service.java中沒有這個方法的實現,也沒有'Application.java'的實現。實施在哪裏? – Eugene

+1

該實現在'ContextWrapper'中。信息的關鍵是,當活動或應用程序初始化時,mBase會在運行時發生變化。 –

+0

感謝您的詳細研究和解釋! – Eugene