首页 > 代码库 > 【Android】Activity生命周期(亲测)

【Android】Activity生命周期(亲测)

测试手机:Nexus 5   系统:4.4

一、测试

测试代码:

 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     @Override16     protected void onCreate(Bundle savedInstanceState) {17         super.onCreate(savedInstanceState);18         setContentView(R.layout.activity_main);19         Log.d("BigFootprint", "onCreate");20     }21 22     @Override23     public void onConfigurationChanged(Configuration newConfig) {24         Log.d("BigFootprint", "onConfigurationChanged");25         super.onConfigurationChanged(newConfig);26     }27 28     @Override29     public View onCreateView(String name, Context context, AttributeSet attrs) {30         Log.d("BigFootprint", "onCreateView");31         return super.onCreateView(name, context, attrs);32     }33 34     @Override35     protected void onDestroy() {36         Log.d("BigFootprint", "onDestroy");37         super.onDestroy();38     }39 40     @Override41     protected void onPause() {42         Log.d("BigFootprint", "onPause");43         super.onPause();44     }45 46     @Override47     protected void onRestart() {48         Log.d("BigFootprint", "onRestart");49         super.onRestart();50     }51 52     @Override53     protected void onRestoreInstanceState(Bundle savedInstanceState) {54         Log.d("BigFootprint", "onRestoreInstanceState");55         super.onRestoreInstanceState(savedInstanceState);56     }57 58     @Override59     protected void onResume() {60         Log.d("BigFootprint", "onResume");61         super.onResume();62     }63 64     @Override65     protected void onSaveInstanceState(Bundle outState) {66         Log.d("BigFootprint", "onSaveInstanceState");67         super.onSaveInstanceState(outState);68     }69 70     @Override71     protected void onStart() {72         Log.d("BigFootprint", "onStart");73         super.onStart();74     }75 76     @Override77     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     <application12         android:allowBackup="true"13         android:icon="@drawable/ic_launcher"14         android:label="@string/app_name"15         android:theme="@style/AppTheme" >16         <activity17             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如下:

生命周期非常正常。当Activity显示的时候,屏幕暗掉,LOG如下:

红框中为多打印的3个生命周期过程,可以看到onSaveInstanceState的调用时机!亮起屏幕,LOG如下:

生命周期一如文档所说。如果按下Home键退出,则LOG如下:

可以看到,和屏幕暗掉的LOG完全一样。重新点击应用图标打开Activity,得到如下LOG:

这个时候并没有去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     <application14         android:allowBackup="true"15         android:icon="@drawable/ic_launcher"16         android:label="@string/app_name"17         android:theme="@style/AppTheme" >18         <activity19             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     <application14         android:allowBackup="true"15         android:icon="@drawable/ic_launcher"16         android:label="@string/app_name"17         android:theme="@style/AppTheme" >18         <activity19             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。

 

二、结论

  在网上看到很多的资料讲述生命周期,结论应该只有一个:生命周期会因为系统版本甚至因为定制等各种因素而各有差异。所以本文一开始就给出了测试环境。上面的测试只在一种环境下完成,不能代表所有系统和所有机型。读者如需了解问题,还应该在当前环境下自己去进行测试。但是由此依然可以得出一些结论:

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方法;

 

最后根据这次试验,总结一下Activity认为意外关闭的三种场景:

1)屏幕暗下去;

2)按下HOME键退出Activity;

3)横竖屏切换;

这三种情景都会导致Activity调用onSaveInstanceState去保存自己的状态以便于恢复。