1. 程式人生 > >Android面試題-Context原理分析

Android面試題-Context原理分析

本文配套視訊

原始碼分析相關面試題

與XMPP相關面試題

與效能優化相關面試題

與登入相關面試題

與開發相關面試題

談一下你對Android中的context的理解,在一個應用程式中有多少個context例項?

一、 什麼是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例項

熟悉了Context的繼承關係後,我們接下來分析應用程式在什麼情況需要建立Context物件的?應用程式建立Context例項的情況有如下幾種情況:

1) 建立Application 物件時, 而且整個App共一個Application物件
2) 建立Service物件時
3) 建立Activity物件時

因此應用程式App共有的Context數目公式為:

總Context例項個數 = Service個數 + Activity個數 + 1(Application對應的Context例項)

1、建立Application物件的Context:
首先新建一個MyApplication並讓它繼承自Application,然後在AndroidManifest.xml檔案中對MyApplication進行指定,如下所示:

<application
    android:name=".MyApplication"
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    ......
</application>

指定完成後,當我們的程式啟動時Android系統就會建立一個MyApplication的例項,通過如下程式碼獲取到它的例項:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MyApplication myApp = (MyApplication) getApplication();
        Log.d("TAG", "getApplication is " + myApp);
    }

}

可以看到,程式碼很簡單,只需要呼叫getApplication()方法就能拿到我們自定義的Application的例項了,列印結果如下所示:

那麼除了getApplication()方法,其實還有一個getApplicationContext()方法,這兩個方法看上去好像有點關聯,那麼它們的區別是什麼呢?我們將程式碼修改一下:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MyApplication myApp = (MyApplication) getApplication();
        Log.d("TAG", "getApplication is " + myApp);
        Context appContext = getApplicationContext();
        Log.d("TAG", "getApplicationContext is " + appContext);
    }
}

同樣,我們把getApplicationContext()的結果列印了出來,現在重新執行程式碼,結果如下圖所示:

打印出的結果是一樣的呀,連後面的記憶體地址都是相同的,看來它們是同一個物件。其實這個結果也很好理解,Application本身就是一個Context,所以這裡獲取getApplicationContext()得到的結果就是MyApplication本身的例項。

那麼有的朋友可能就會問了,既然這兩個方法得到的結果都是相同的,那麼Android為什麼要提供兩個功能重複的方法呢?實際上這兩個方法在作用域上有比較大的區別。getApplication()方法的語義性非常強,一看就知道是用來獲取Application例項的,但是這個方法只有在Activity和Service中才能呼叫的到。那麼也許在絕大多數情況下我們都是在Activity或者Service中使用Application的,但是如果在一些其它的場景,比如BroadcastReceiver中也想獲得Application的例項,這時就可以藉助getApplicationContext()方法了,如下所示:

public class MyReceiver extends BroadcastReceiver {  

    @Override  
    public void onReceive(Context context, Intent intent) {  
        MyApplication myApp = (MyApplication) context.getApplicationContext();  
        Log.d("TAG", "myApp is " + myApp);  
    }  

}  

也就是說,getApplicationContext()方法的作用域會更廣一些,任何一個Context的例項,只要呼叫getApplicationContext()方法都可以拿到我們的Application物件。

  • 歡迎關注微信公眾號,長期推薦技術文章和技術視訊