編寫Activity時遇到的一個問題,在此記錄,也分享下,Activity寫好運行後,genimotion開啓應用,卻發現界面不顯示內容,後來發現標題欄label也不顯示。於是開始排查問題原因,在確認setContentView調用,佈局文件填充、編寫無誤,as沒有問題情況下,gradle沒有問題下,因爲gradle編譯其他應用正常,依然不顯示,奇怪了,不過還是要繼續找問題出在哪兒。
最終問題出現在onCreate方法,是不是很驚訝,的確,壓根沒想到onCreate方法會出什麼問題。
到底出什麼問題呢,發現,Activity的Context中有兩個onCreate方法,具體如下:
android 5.0 (即android 4.4w,API level是android 20)之前的Activity源碼:
protected void onCreate(Bundle savedInstanceState){
//...
}
final void performCreate(Bundle icicle) {
onCreate(icicle);
mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(com.android.internal.R.styleable.Window_windowNoDisplay, false);
mFragments.dispatchActivityCreated();
}
protected void onRestoreInstanceState(Bundle savedInstanceState) {
//....
}
protected void onSaveInstanceState(Bundle outState) {
//...
}
android 5.0(包含android 5.0,API level是android 21)以後Activity源碼:
protected void onCreate(@Nullable Bundle savedInstanceState) {
//...
}
public void onCreate(@Nullable Bundle savedInstanceState,@Nullable PersistableBundle persistentState) {
onCreate(savedInstanceState);
}
final void performCreate(Bundle icicle) {
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
onCreate(icicle, persistentState);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
final void performCreateCommon() {
mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(com.android.internal.R.styleable.Window_windowNoDisplay, false);
mFragments.dispatchActivityCreated();
mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
}
<pre name="code" class="java"> protected void onSaveInstanceState(Bundle outState) {
//...
}
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {onSaveInstanceState(outState);
}
<pre name="code" class="java"> protected void onRestoreInstanceState(Bundle savedInstanceState) {
//....
}
public void onRestoreInstanceState(Bundle savedInstanceState,PersistableBundle persistentState) {
if (savedInstanceState != null) {
onRestoreInstanceState(savedInstanceState);
}
}
對比看出:
android 5.0之後,在原有的onCreate方法上,重載出新onCreate方法,該方法是public修飾,帶有兩個參數,Bundle、PersistableBundle,重載後的onCreate方法裏調用了原有的onCreate方法
android 5.0之後,在原有performCreate方法上,重載新performCreate方法,並帶有兩個參數,Bundle、PersistableBundle,方法內部分別對應調用onCreate的方法
android 5.0之後,將原有performCreate部分代碼抽取,新增方法performCreateCommon
android 5.0之後,onSaveInstanceState,onRestoreInstanceState同樣進行重載
原有onCreate方法,是這麼描述:
當Activity啓動的時候,會調用該方法,方法內填充界面內容,初始化控件,初始化數據等
重載的onCreate方法,是這麼描述:
跟原有onCreate相同,但是調用該方法的Activity比較特別,這些Activity必須是android.R.attr下的persistableMode模式,並且設置爲persistAcrossReboots
在Manifest中的activity設置屬性:
android:persistableMode="persistAcrossReboots"
這裏有個疑問,是不是將Activity的persistMode配置成persistAcrossReboots,就會在啓動Activity時,調用帶有PersistableBundle的onCreate方法呢?
配置persistMode配置成persistAcrossReboots,重寫onCreate(Bundle icicle, PersistableBundle persistentState) ,加載佈局,初始化控件,結果,界面不顯示
不配置persistMode,重寫onStart(Bundle icicle),加載佈局,初始化控件,結果,界面顯示
結論:一般情況下,Activity的創建,重寫的是onStart(Bundle icicle),而非onCreate(Bundle icicle, PersistableBundle persistentState),正常啓動Activity,是不會調用後者的,即便後者內部寫了加載佈局,初始化控件等這些代碼,也不會執行