Androidのライフサイクルを実機で検証してみた
Androidのライフサイクルについては色々なところで解説されているが、実際に端末で操作を行った際に、OnCreate等のメソッドがどう呼ばれるのかがいまいち分かりづらかったので、軽くまとめてみた。
検証に使用した端末は、Nexus S(2.3.6)。
検証用Activity
次のような実装に。
- ライフサイクルに関連する7つのメソッド(よく解説の図とかに載ってるやつ)を全てオーバーライドし、呼び出されたメソッドに対応する文字列をログに出力する。
- 上記に加え、onRestoreInstanceState/onSaveInstanceStateも同じように見る。
- finish()を呼んだときの挙動も見るため、Viewにボタンを1個配置し、クリックされたときにfinish()を呼ぶ。
- onRestore()でActivityのインスタンスとインスタンスフィールド、クラスとstaticフィールドのhashCode()を出力する。
HelloAndroidActivity.java
public class HelloAndroidActivity extends Activity implements OnClickListener { private static final String TAG = "LifeCycleTest"; private Object instanceField = new Object(); private static Object staticField = new Object(); /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { Log.d(TAG, "----------OnCreate"); super.onCreate(savedInstanceState); setContentView(R.layout.main); ((Button) findViewById(R.id.finish_button)).setOnClickListener(this); } @Override protected void onStart() { Log.d(TAG, "----------OnStart"); super.onPause(); } @Override protected void onResume() { Log.d(TAG, "----------OnResume"); Log.d(TAG, String.format( "Activity-Class:hashCode=%1$x,static field hashCode:%1$x", this .getClass().hashCode(), HelloAndroidActivity.staticField.hashCode())); Log.d(TAG, String.format( "Activity-Instance:hashCode=%1$x,instance field hashCode:%1$x", this.hashCode(), this.instanceField.hashCode())); super.onResume(); } @Override protected void onRestart() { Log.d(TAG, "----------OnRestart"); super.onPause(); } @Override protected void onPause() { Log.d(TAG, "----------OnPause"); super.onPause(); } @Override protected void onStop() { Log.d(TAG, "----------OnStop"); super.onPause(); } @Override protected void onDestroy() { Log.d(TAG, "----------OnDestroy"); super.onPause(); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { Log.d(TAG, "----------onRestoreInstanceState"); super.onRestoreInstanceState(savedInstanceState); } @Override protected void onSaveInstanceState(Bundle outState) { Log.d(TAG, "----------onSaveInstanceState"); super.onSaveInstanceState(outState); } @Override public void onClick(View v) { finish(); } }
main.xml
<?xml version="1.0" encoding="utf-8"?> <Button xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/finish_button" android:text="終了"> </Button>
色々動かしてみる。
アプリを起動
10-28 15:05:12.542: DEBUG/LifeCycleTest(25813): ----------OnCreate 10-28 15:05:12.562: DEBUG/LifeCycleTest(25813): ----------OnStart 10-28 15:05:12.562: DEBUG/LifeCycleTest(25813): ----------OnResume 10-28 15:05:12.566: DEBUG/LifeCycleTest(25813): Activity-Class:hashCode=40515d80,static field hashCode:40515d80 10-28 15:05:12.566: DEBUG/LifeCycleTest(25813): Activity-Instance:hashCode=40516160,instance field hashCode:40516160
バックボタンでアプリを閉じる
10-28 15:05:43.085: DEBUG/LifeCycleTest(25813): ----------OnPause (中略) 10-28 15:05:43.605: DEBUG/LifeCycleTest(25813): ----------OnStop 10-28 15:05:43.605: DEBUG/LifeCycleTest(25813): ----------OnDestroy
もう一回起動
10-28 15:06:05.660: DEBUG/LifeCycleTest(25813): ----------OnCreate 10-28 15:06:05.664: DEBUG/LifeCycleTest(25813): ----------OnStart 10-28 15:06:05.664: DEBUG/LifeCycleTest(25813): ----------OnResume 10-28 15:06:05.664: DEBUG/LifeCycleTest(25813): Activity-Class:hashCode=40515d80,static field hashCode:40515d80 10-28 15:06:05.664: DEBUG/LifeCycleTest(25813): Activity-Instance:hashCode=4051f0a8,instance field hashCode:4051f0a8
ホームボタンでアプリを閉じる
10-28 15:06:55.167: DEBUG/LifeCycleTest(25813): ----------onSaveInstanceState 10-28 15:06:55.167: DEBUG/LifeCycleTest(25813): ----------OnPause
再び起動
10-28 15:07:14.578: DEBUG/LifeCycleTest(25813): ----------OnRestart 10-28 15:07:14.578: DEBUG/LifeCycleTest(25813): ----------OnStart 10-28 15:07:14.578: DEBUG/LifeCycleTest(25813): ----------OnResume 10-28 15:07:14.578: DEBUG/LifeCycleTest(25813): Activity-Class:hashCode=40515d80,static field hashCode:40515d80 10-28 15:07:14.578: DEBUG/LifeCycleTest(25813): Activity-Instance:hashCode=4051f0a8,instance field hashCode:4051f0a8
finish()
10-28 15:07:40.613: DEBUG/LifeCycleTest(25813): ----------OnPause (中略) 10-28 15:07:41.058: DEBUG/LifeCycleTest(25813): ----------OnStop 10-28 15:07:41.058: DEBUG/LifeCycleTest(25813): ----------OnDestroy
もう一回起動
10-28 15:08:05.117: DEBUG/LifeCycleTest(25813): ----------OnCreate 10-28 15:08:05.121: DEBUG/LifeCycleTest(25813): ----------OnStart 10-28 15:08:05.121: DEBUG/LifeCycleTest(25813): ----------OnResume 10-28 15:08:05.121: DEBUG/LifeCycleTest(25813): Activity-Class:hashCode=40515d80,static field hashCode:40515d80 10-28 15:08:05.121: DEBUG/LifeCycleTest(25813): Activity-Instance:hashCode=40517968,instance field hashCode:40517968
スクリーンオフ
10-28 15:08:20.882: DEBUG/LifeCycleTest(25813): ----------onSaveInstanceState 10-28 15:08:20.882: DEBUG/LifeCycleTest(25813): ----------OnPause
スクリーンオン
10-28 15:08:39.031: DEBUG/LifeCycleTest(25813): ----------OnResume 10-28 15:08:39.031: DEBUG/LifeCycleTest(25813): Activity-Class:hashCode=40515d80,static field hashCode:40515d80 10-28 15:08:39.031: DEBUG/LifeCycleTest(25813): Activity-Instance:hashCode=40517968,instance field hashCode:40517968
パスワードロックをかけているが、ロックを外す前にログが出た。
端末の向きを変える→戻す
10-28 15:16:04.257: DEBUG/LifeCycleTest(25813): ----------onSaveInstanceState 10-28 15:16:04.257: DEBUG/LifeCycleTest(25813): ----------OnPause 10-28 15:16:04.257: DEBUG/LifeCycleTest(25813): ----------OnStop 10-28 15:16:04.257: DEBUG/LifeCycleTest(25813): ----------OnDestroy 10-28 15:16:04.261: DEBUG/LifeCycleTest(25813): ----------OnCreate 10-28 15:16:04.265: DEBUG/LifeCycleTest(25813): ----------OnStart 10-28 15:16:04.265: DEBUG/LifeCycleTest(25813): ----------onRestoreInstanceState 10-28 15:16:04.265: DEBUG/LifeCycleTest(25813): ----------OnResume 10-28 15:16:04.265: DEBUG/LifeCycleTest(25813): Activity-Class:hashCode=40515d80,static field hashCode:40515d80 10-28 15:16:04.265: DEBUG/LifeCycleTest(25813): Activity-Instance:hashCode=40538598,instance field hashCode:40538598 (中略) 10-28 15:16:07.468: DEBUG/LifeCycleTest(25813): ----------onSaveInstanceState 10-28 15:16:07.468: DEBUG/LifeCycleTest(25813): ----------OnPause 10-28 15:16:07.468: DEBUG/LifeCycleTest(25813): ----------OnStop 10-28 15:16:07.468: DEBUG/LifeCycleTest(25813): ----------OnDestroy 10-28 15:16:07.468: DEBUG/LifeCycleTest(25813): ----------OnCreate 10-28 15:16:07.472: DEBUG/LifeCycleTest(25813): ----------OnStart 10-28 15:16:07.472: DEBUG/LifeCycleTest(25813): ----------onRestoreInstanceState 10-28 15:16:07.476: DEBUG/LifeCycleTest(25813): ----------OnResume 10-28 15:16:07.476: DEBUG/LifeCycleTest(25813): Activity-Class:hashCode=40515d80,static field hashCode:40515d80 10-28 15:16:07.476: DEBUG/LifeCycleTest(25813): Activity-Instance:hashCode=40539f20,instance field hashCode:40539f20
電話がかかってきた→切る
10-28 15:17:06.281: DEBUG/LifeCycleTest(25813): ----------onSaveInstanceState 10-28 15:17:06.281: DEBUG/LifeCycleTest(25813): ----------OnPause (中略) 10-28 15:17:06.406: INFO/power(109): *** set_screen_state 1 10-28 15:17:06.609: DEBUG/LifeCycleTest(25813): ----------OnStop (中略) 10-28 15:17:09.699: DEBUG/LifeCycleTest(25813): ----------OnRestart 10-28 15:17:09.699: DEBUG/LifeCycleTest(25813): ----------OnStart 10-28 15:17:09.699: DEBUG/LifeCycleTest(25813): ----------OnResume 10-28 15:17:09.699: DEBUG/LifeCycleTest(25813): Activity-Class:hashCode=40515d80,static field hashCode:40515d80 10-28 15:17:09.699: DEBUG/LifeCycleTest(25813): Activity-Instance:hashCode=40539f20,instance field hashCode:40539f20
まれにOnDestroy()まで呼ばれ、OnCreate()から始まるときもある。
分かったこと
大体書籍やWebに書いてあるのと同じ動作であったが、下記は個人的に今回分かったこと。
- onRestoreInstanceState()は画面の回転以外では呼ばれない。
- ホームボタンを押した際の動作は、アプリの終了ではなく一時停止。(ホームアプリが起動してアプリが一時停止した状態なのだろう。)
- バックボタンとfinish()時の動作は同じ。(これらは終了扱いか。)
- OnDestroy()が呼ばれるとインスタンスは破棄されるが、クラスはアンロードされない。