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()が呼ばれるとインスタンスは破棄されるが、クラスはアンロードされない。