【Android】Activity生命週期(親測)

測試手機:Nexus 5   系統:4.4android

1、測試app

測試代碼:ide

 1 package com.example.androidalarm;
 2 
 3 import android.app.Activity;
 4 import android.content.Context;
 5 import android.content.res.Configuration;
 6 import android.os.Bundle;
 7 import android.util.AttributeSet;
 8 import android.util.Log;
 9 import android.view.View;
10 import android.widget.Button;
11 
12 public class MainActivity extends Activity {
13     Button addButton, cancelButton;
14     
15     @Override
16     protected void onCreate(Bundle savedInstanceState) {
17         super.onCreate(savedInstanceState);
18         setContentView(R.layout.activity_main);
19         Log.d("BigFootprint", "onCreate");
20     }
21 
22     @Override
23     public void onConfigurationChanged(Configuration newConfig) {
24         Log.d("BigFootprint", "onConfigurationChanged");
25         super.onConfigurationChanged(newConfig);
26     }
27 
28     @Override
29     public View onCreateView(String name, Context context, AttributeSet attrs) {
30         Log.d("BigFootprint", "onCreateView");
31         return super.onCreateView(name, context, attrs);
32     }
33 
34     @Override
35     protected void onDestroy() {
36         Log.d("BigFootprint", "onDestroy");
37         super.onDestroy();
38     }
39 
40     @Override
41     protected void onPause() {
42         Log.d("BigFootprint", "onPause");
43         super.onPause();
44     }
45 
46     @Override
47     protected void onRestart() {
48         Log.d("BigFootprint", "onRestart");
49         super.onRestart();
50     }
51 
52     @Override
53     protected void onRestoreInstanceState(Bundle savedInstanceState) {
54         Log.d("BigFootprint", "onRestoreInstanceState");
55         super.onRestoreInstanceState(savedInstanceState);
56     }
57 
58     @Override
59     protected void onResume() {
60         Log.d("BigFootprint", "onResume");
61         super.onResume();
62     }
63 
64     @Override
65     protected void onSaveInstanceState(Bundle outState) {
66         Log.d("BigFootprint", "onSaveInstanceState");
67         super.onSaveInstanceState(outState);
68     }
69 
70     @Override
71     protected void onStart() {
72         Log.d("BigFootprint", "onStart");
73         super.onStart();
74     }
75 
76     @Override
77     protected void onStop() {
78         Log.d("BigFootprint", "onStop");
79         super.onStop();
80     }
81 }
View Code

XML配置:測試

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 3     package="com.example.androidalarm"
 4     android:versionCode="1"
 5     android:versionName="1.0" >
 6 
 7     <uses-sdk
 8         android:minSdkVersion="8"
 9         android:targetSdkVersion="18" />
10 
11     <application
12         android:allowBackup="true"
13         android:icon="@drawable/ic_launcher"
14         android:label="@string/app_name"
15         android:theme="@style/AppTheme" >
16         <activity
17             android:name="com.example.androidalarm.MainActivity"
18             android:label="@string/app_name" >
19             <intent-filter>
20                 <action android:name="android.intent.action.MAIN" />
21                 <category android:name="android.intent.category.LAUNCHER" />
22             </intent-filter>
23         </activity>
24     </application>
25 </manifest>
View Code

以以上的代碼運行,打開應用,LOG輸出以下「字體

能夠看到,打開Activity的時候,生命週期是符合文檔描述的,可是onCreateView接口會被屢次調用,因此最好不要在這邊實例化數據。按下BACK鍵退出,LOG以下:spa

生命週期很是正常。當Activity顯示的時候,屏幕暗掉,LOG以下:3d

紅框中爲多打印的3個生命週期過程,能夠看到onSaveInstanceState的調用時機!亮起屏幕,LOG以下:code

生命週期一如文檔所說。若是按下Home鍵退出,則LOG以下:orm

能夠看到,和屏幕暗掉的LOG徹底同樣。從新點擊應用圖標打開Activity,獲得以下LOG:xml

這個時候並無去OnCreate,而是調用了方法onRestart方法。

這時候切換屏幕(豎屏切爲橫屏):(備註:由於onCreateView調用次數太多,並且不是重點研究對象,後面去掉此處LOG)

能夠看到切換的時候,生命週期又走了一遍,而且調用了onSaveInstanceState和onRestoreInstanceState方法用於保存和恢復狀態。而後從橫屏恢復爲豎屏,LOG以下:

調用的生命週期過程徹底和上面的切換徹底同樣。

 

接下來要試驗的是,從新在XML文件中配置Activity。

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 3     package="com.example.androidalarm"
 4     android:versionCode="1"
 5     android:versionName="1.0" >
 6 
 7     <uses-sdk
 8         android:minSdkVersion="8"
 9         android:targetSdkVersion="18" />
10 
11     <uses-permission android:name="android.permission.CHANGE_CONFIGURATION"></uses-permission>
12     
13     <application
14         android:allowBackup="true"
15         android:icon="@drawable/ic_launcher"
16         android:label="@string/app_name"
17         android:theme="@style/AppTheme" >
18         <activity
19             android:name="com.example.androidalarm.MainActivity"
20             android:configChanges="orientation"
21             android:label="@string/app_name" >
22             <intent-filter>
23                 <action android:name="android.intent.action.MAIN" />
24                 <category android:name="android.intent.category.LAUNCHER" />
25             </intent-filter>
26         </activity>
27     </application>
28 </manifest>
View Code

多加了一個配置: android:configChanges="orientation"。而且須要添加permission。

這是豎屏——>橫屏——>豎屏切換過程當中打印的LOG,能夠看到,和沒有配置的時候徹底同樣。再配置以下:添加: android:configChanges="orientation|keyboardHidden"

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 3     package="com.example.androidalarm"
 4     android:versionCode="1"
 5     android:versionName="1.0" >
 6 
 7     <uses-sdk
 8         android:minSdkVersion="8"
 9         android:targetSdkVersion="18" />
10 
11     <uses-permission android:name="android.permission.CHANGE_CONFIGURATION"></uses-permission>
12     
13     <application
14         android:allowBackup="true"
15         android:icon="@drawable/ic_launcher"
16         android:label="@string/app_name"
17         android:theme="@style/AppTheme" >
18         <activity
19             android:name="com.example.androidalarm.MainActivity"
20             android:configChanges="orientation|keyboardHidden"
21             android:label="@string/app_name" >
22             <intent-filter>
23                 <action android:name="android.intent.action.MAIN" />
24                 <category android:name="android.intent.category.LAUNCHER" />
25             </intent-filter>
26         </activity>
27     </application>
28 </manifest>
View Code

打印的LOG仍是同樣,接下來再配置:改爲android:configChanges="orientation|screenSize", 切換橫豎屏打印的LOG以下:

注意,這裏也是豎屏——>橫屏——>豎屏切換,每次切換隻打印一行LOG。

 

2、結論

  在網上看到不少的資料講述生命週期,結論應該只有一個:生命週期會由於系統版本甚至由於定製等各類因素而各有差別。因此本文一開始就給出了測試環境。上面的測試只在一種環境下完成,不能表明全部系統和全部機型。讀者如需瞭解問題,還應該在當前環境下本身去進行測試。可是由此依然能夠得出一些結論:

1)onCreateView接口會被屢次調用,在這個接口中的代碼要好好考慮,實例化數據,加載資源的動做最好不要放在這個方法中;

2)若是不是程序主動關閉Activity(好比按下回退鍵),onPause()以後會調用onSaveInstanceState方法保存狀態,此後恢復Activity,若是在這之間調用了onDestory,即Activity被意外銷燬,會在onStart()和onResume()之間調用onRestoreInstanceState方法恢復狀態,不然,會以onRestart->onStart()->onResume()的順序從新打開Activity;

3)若是不配置Activity的configChanges或者配置沒有起效果(注:如何起效果,視環境而定,最保險的方案目前是:android:configChanges="orientation|screenSize|keyboardHidden"),則在橫豎屏切換的時候,會從新走一遍生命週期,不然,只會調用onConfigurationChanged方法;

 

補充一下關於configChanges的參數值解釋:

Value Description
「mcc「 The IMSI mobile country code (MCC) has changed — that is, a SIM hasbeen detected and updated the MCC.移動國家號碼,由三位數字組成,每一個國家都有本身獨立的MCC,能夠識別手機用戶所屬國家。
「mnc「 The IMSI mobile network code (MNC) has changed — that is, a SIM hasbeen detected and updated the MNC.移動網號,在一個國家或者地區中,用於區分手機用戶的服務商。
「locale「 The locale has changed — for example, the user has selected a new language that text should be displayed in.用戶所在地區發生變化。
「touchscreen「 The touchscreen has changed. (This should never normally happen.)
「keyboard「 The keyboard type has changed — for example, the user has plugged in an external keyboard.鍵盤模式發生變化,例如:用戶接入外部鍵盤輸入。
「keyboardHidden「 The keyboard accessibility has changed — for example, the user has slid the keyboard out to expose it.用戶打開手機硬件鍵盤
「navigation「 The navigation type has changed. (This should never normally happen.)
「orientation「 The screen orientation has changed — that is, the user has rotated the device.設備旋轉,橫向顯示和豎向顯示模式切換。
「fontScale「 The font scaling factor has changed — that is, the user has selected a new global font size.全局字體大小縮放發生改變

根據這份解釋,我的感受其實系統是有BUG的,理論上configChanges=orientation這樣的配置在設備旋轉後就應該會去調用onConfigurationChanged方法,但實際上連親生兒子也不遵循。

 

最後根據此次試驗,總結一下Activity認爲意外關閉的三種場景:

1)屏幕暗下去;

2)按下HOME鍵退出Activity;

3)橫豎屏切換;

這三種情景都會致使Activity調用onSaveInstanceState去保存本身的狀態以便於恢復。

相關文章
相關標籤/搜索