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物件。
- 歡迎關注微信公眾號,長期推薦技術文章和技術視訊