生命周期:1.典型情況下的生命周期 :有用戶參與的情況下(當然手機的各種狀態都是理想情況下)
2.異常情況下的生命周期:指的是現實情況下,例如手機內容不足。Activity被系統回收,
還有就是當前Configuration發生變化從而導致Activity被銷毀重建等。(Actvity在異常情況下,表現十分微妙。)
1.典型情況下的生命周期:如下圖所示
如下代碼所示:
public classMainActivityextendsAppCompatActivity {
private static finalStringTAG="bill";
@Override
protected voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG,"onCreate()");
}
@Override
protected voidonRestart() {
super.onRestart();
Log.d(TAG,"onRestart()");
}
@Override
protected voidonStart() {
super.onStart();
Log.d(TAG,"onStart()");
}
@Override
protected voidonResume() {
super.onResume();
Log.d(TAG,"onResume()");
}
@Override
protected voidonPause() {
super.onPause();
Log.d(TAG,"onPause()");
}
@Override
protected voidonStop() {
super.onStop();
Log.d(TAG,"onStop()");
}
@Override
protected voidonDestroy() {
super.onDestroy();
Log.d(TAG,"onDestroy()");
}
}
上面代碼是把activity中所有的生命周期都打印了出來。
那么我們可以看到,第一次啟動的時候運行順序:
以下就不意義列舉各種正常情況了:
只寫結果:
1.正常情況下,oncreate() onstart() onresume()
2.如果當前activity A打開另一個activity B或點擊home鍵進入桌面,那么此時執行activity A的onpause() onstop()方法,當然此時有一種特殊的activity B是不會調用onstop()方法,只是會調用onpause()方法,那就是,此activity B的主題是透明色的。
3.當回到activity A的時候,調用 onRestart() onstart() onresume()方法
4.當activity被系統回收以后再次打開,生命周期的調用順序和1是一樣的,但是僅僅是生命周期的調用順序,并不代表其他過程也一樣。
5.生命周期配對:oncreate() ondestroy()
onstar() onstop()
onresume() onpause()
那么問題來了:
activity A打開activity B的時候,activity A的onpause()和activity的onResume()方法執行的先后順序是怎樣的?
打印日志可以看出,兩個activity調用的生命周期方法,竟然載同一個線程內,如圖
從上圖可以看出,activity A的onpause()方法先執行,然后執行依次activity B的onCreate() onstart() onResume()方法,再去執行A的onstop()等方法。
另一方面,Android官方也說過,不能在onpause中做一些重量級操作,畢竟要當前的activity先執行完onpause()才能再執行下一個activity的開始生命周期。
2.異常情況下的生命周期
1)資源相關的activity發生改變,導致activity被殺死并重建
例子:資源相關的配置發生改變、系統內存不足的時候,activity可能會被殺死。
在activity下添加以下方法:
@Override
public voidonSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(OUTSTATE,"我被保存下來了");
Log.d(TAG,"Thread :"+ Thread.currentThread() +",onSaveInstanceState()");
}
@Override
public voidonRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if(savedInstanceState !=null) {
String outstate = savedInstanceState.getString(OUTSTATE);
Log.d(TAG,"onRestoreInstanceState() outstates = "+ outstate);
}
Log.d(TAG,"Thread :"+ Thread.currentThread() +",onRestoreInstanceState()");
}
分析:資源相關配置發生改變:
從豎屏轉換成橫屏的時候,日志如下:
從橫屏轉換成豎屏的時候,日志如下:
此時知道,我們的activity如果屏幕旋轉,會造成生命周期的改變,一般來說是這樣:
onpause() -> onsaveinstancestate() -> onstop() -> ondestroy() -> oncreate() -> onstart() -> onrestoreinstancestate() ->onresume()
而且onrestoreinstancestate()能獲取到onsaveinstancestate()保存下來的數據,并且調用順序是在onstart()方法之后。
但是,有一點,日志里邊沒有說明的:onsaveinstancestate()方法的調用時機是在onstop()之前,而且又和onpause()沒有時間順序上的關系。(待驗證)
值得說明的一個是:在執行完activity的onsaveinstancestate()方法之后,還會activity會委托window保存數據,接著window委托他的頂級容器去保存數據,頂層容器是一個viewgroup,然后頂層容器會再去通知他的子元素,例如TextView去調用它的onsaveinstancestate()方法去保存它的數據。這是一個典型的委托思想,在view的繪制過程和分發機制中也是用的類似的思想。
當系統資源內存不足的時候,會由優先級從低到高依次kill activity。
這里的優先級劃分:前臺展示的activity最高,可見但非前臺的activity中級,后臺activity優先級最低。(這時候可以根據生命周期是否調用onpause onstop方法判斷優先級,例如最高級是沒有執行兩個方法,中級是之執行了onpause方法,最低級是執行了兩個方法)
剛才說的第一種情況,當屏幕的橫豎屏改變的時候,activity會重新繪制,會把生命周期先結束再重新開始,那么如果我不想重新繪制activity的話,應該怎么做呢?
答:在manifest給需要設置的activity添加:android:configChanges="orientation",
當然在sdk>13的時候還要加上一個屬性scrrenSize,變成:android:configChanges="screenSize|orientation",設置了當前的屬性,顧名思義:這個是配置改變的時候,屏幕的橫豎配置改變的時候。
并且加上下面的代碼:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
switch(newConfig.orientation){
case Configuration.ORIENTATION_LANDSCAPE:
Log.d(TAG,"變成了橫著的");
break;
case Configuration.ORIENTATION_PORTRAIT:
Log.d(TAG,"變成了豎著的");
break;
}
}
當屏幕的橫豎改變的時候,打印日志為: