Activityライフサイクル
ライフサイクルをきっちり理解したうえでアプリ開発をしていかないと
とんでもないソフトが出来上がるため、注意が必要です。
色々Andoroidをいじってきましたが、いまだにライフサイクルについての知識が乏しかったので
一度まとめてみた。
アクティビティが開始(アンドロイドアプリ起動)されて(アンドロイドアプリ終了)破棄されるまでを
アクティビティのライフサイクルと呼ぶ。
ライフサイクルの間は、アクティビティは色々な状態を遷移し、対応する関数が呼ばれる。
ライフサイクル関係のメソッド一覧
onCreate()アクティビティが初めて作成されるときに呼び出されます。
onStart()
アクティビティがユーザーから見えるようになる直前に呼び出されます。
onResume()
アクティビティがユーザーとの対話を開始する直前に呼び出されます。
onRestart()
アクティビティが停止した後、それをもう一度開始する直前に呼び出されます。
onPause()
システムが別のアクティビティを開始しようとしているときに呼び出されます。
onStop()
アクティビティがユーザーから見えなくなったときに呼び出されます。
onDestroy()
アクティビティが破棄される前に呼び出されます。
メソッドが呼ばれたときのログをとり
いくつかの画面遷移のパターンを操作したときに呼ばれるメソッドとその順番を確認してみました。
全体のソースは下記の通りです
package com.example.activitytest;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
public class MainActivity extends Activity {
private final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d(TAG,"onCreate");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
Log.d(TAG,"onCreateOptionsMenu");
return true;
}
@Override
protected void onDestroy() {
// TODO 自動生成されたメソッド・スタブ
super.onDestroy();
Log.d(TAG,"onDestroy");
}
@Override
protected void onPause() {
// TODO 自動生成されたメソッド・スタブ
super.onPause();
Log.d(TAG,"onPause");
}
@Override
protected void onRestart() {
// TODO 自動生成されたメソッド・スタブ
super.onRestart();
Log.d(TAG,"onRestart");
}
@Override
protected void onResume() {
// TODO 自動生成されたメソッド・スタブ
super.onResume();
Log.d(TAG,"onResume");
}
@Override
protected void onStart() {
// TODO 自動生成されたメソッド・スタブ
super.onStart();
Log.d(TAG,"onStart");
}
@Override
protected void onStop() {
// TODO 自動生成されたメソッド・スタブ
super.onStop();
Log.d(TAG,"onStop");
}
}
●アプリ起動時
10:36:29.435: D/MainActivity: onCreate10:36:29.435: D/MainActivity: onStart
10:36:29.440: D/MainActivity: onResume
10:36:29.650: D/MainActivity: onCreateOptionsMenu
アプリのメイン画面が表示される。
●アプリ起動後、端末のバックボタン押下時
10:45:56.015: D/MainActivity: onPause10:45:56.645: D/MainActivity: onStop
10:45:56.645: D/MainActivity: onDestroy
端末トップ画面が表示される。
●アプリ起動後、端末のホームボタン押下時
10:48:01.060: D/MainActivity: onPause10:48:01.735: D/MainActivity: onStop
端末トップ画面が表示される。ここからまたアプリのアイコンをクリックすると・・・
10:49:04.085: D/MainActivity: onRestart
10:49:04.085: D/MainActivity: onStart
10:49:04.085: D/MainActivity: onResume
画面はメイン画面が表示される。
●アプリ起動中、着信した時
10:48:01.060: D/MainActivity: onPause10:48:01.735: D/MainActivity: onStop
着信画面が表示される。
●アプリ起動後、アプリの終了ボタン押下(finish())
11:28:40.845: D/MainActivity: onPause11:28:41.540: D/MainActivity: onStop
11:28:41.540: D/MainActivity: onDestroy
端末トップ画面が表示される。
●アプリ起動中、端末がスリープ状態になる
11:29:53.845: D/MainActivity: onPause11:29:54.540: D/MainActivity: onStop
画面の電源がOFFになる。ここから再開すると・・・
11:31:04.085: D/MainActivity: onRestart
11:31:04.085: D/MainActivity: onStart
11:31:04.085: D/MainActivity: onResume
●アプリ起動に画面の向きを変える(縦向きから横向き)
11:38:59.410: D/MainActivity: onPause11:38:59.410: D/MainActivity: onStop
11:38:59.410: D/MainActivity: onDestroy
11:38:59.570: D/MainActivity: onCreate
11:38:59.570: D/MainActivity: onStart
11:38:59.570: D/MainActivity: onCreateOptionsMenu
11:38:59.570: D/MainActivity: onResume
向きが変わった画面が表示される。さらに向きを元に戻すと。
11:44:38.890: D/MainActivity: onPause
11:44:38.890: D/MainActivity: onStop
11:44:38.890: D/MainActivity: onDestroy
11:44:39.120: D/MainActivity: onCreate
11:44:39.125: D/MainActivity: onStart
11:44:39.140: D/MainActivity: onCreateOptionsMenu
11:44:39.150: D/MainActivity: onResume
向きを変えるとonDestroyまでよんでるんですね・・・
これはしりませんでした(;´Д`)
カテゴリーへ
画面遷移時ライフサイクル
前回はアプリに画面が1つしかないパターンで検証しましたが
今回は複数画面が存在し、それぞれ画面遷移した際にどうなるかを見ていきたいと思います。
画面構成は以下のようにします。
メイン画面にはSub01に移動するボタンとアプリ終了ボタン。
Sub01画面にはメイン画面に移動するボタンSub02画面に移動するボタン。
Sub02画面にはSub01画面に移動するボタン。
以降にソース全体を記述します
●MainActivity.java
package com.example.activitytest;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener{
private final String TAG = "MainActivity";
private Button sub01OpenButton = null; //sub01画面表示ボタン
private Button appEndButton = null; //アプリ終了ボタン
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d(TAG,"onCreate");
//アプリ終了ボタン初期化
this.appEndButton = (Button)findViewById(R.id.app_end_button);
this.appEndButton.setOnClickListener(this);
//サブ画面表示ボタン初期化
this.sub01OpenButton = (Button)findViewById(R.id.sub01_open_button);
this.sub01OpenButton.setOnClickListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
Log.d(TAG,"onCreateOptionsMenu");
return true;
}
@Override
protected void onDestroy() {
// TODO 自動生成されたメソッド・スタブ
super.onDestroy();
Log.d(TAG,"onDestroy");
}
@Override
protected void onPause() {
// TODO 自動生成されたメソッド・スタブ
super.onPause();
Log.d(TAG,"onPause");
}
@Override
protected void onRestart() {
// TODO 自動生成されたメソッド・スタブ
super.onRestart();
Log.d(TAG,"onRestart");
}
@Override
protected void onResume() {
// TODO 自動生成されたメソッド・スタブ
super.onResume();
Log.d(TAG,"onResume");
}
@Override
protected void onStart() {
// TODO 自動生成されたメソッド・スタブ
super.onStart();
Log.d(TAG,"onStart");
}
@Override
protected void onStop() {
// TODO 自動生成されたメソッド・スタブ
super.onStop();
Log.d(TAG,"onStop");
}
@Override
public void onClick(View v) {
// TODO 自動生成されたメソッド・スタブ
switch(v.getId()) {
case R.id.app_end_button:
//終了ボタンが押された
//画面終了
this.finish();
break;
case R.id.sub01_open_button:
//Sub01へボタンが押された
//Intentオブジェクト生成
Intent intent = new Intent(this,Sub01Activity.class);
//画面呼び出し
startActivity(intent);
break;
}
}
}
●Sub01Activity.java
package com.example.activitytest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class Sub01Activity extends Activity implements OnClickListener{
private final String TAG = "Sub01Activity";
private Button sub02OpenButton = null; //sub02画面表示ボタン
private Button menuOpenButton = null; //メニュに戻るボタン
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sub01);
Log.d(TAG,"onCreate");
this.sub02OpenButton = (Button)findViewById(R.id.sub02_open_button);
this.sub02OpenButton.setOnClickListener(this);
this.menuOpenButton = (Button)findViewById(R.id.main_open_button);
this.menuOpenButton.setOnClickListener(this);
}
@Override
protected void onDestroy() {
// TODO 自動生成されたメソッド・スタブ
super.onDestroy();
Log.d(TAG,"onDestroy");
}
@Override
protected void onPause() {
// TODO 自動生成されたメソッド・スタブ
super.onPause();
Log.d(TAG,"onPause");
}
@Override
protected void onRestart() {
// TODO 自動生成されたメソッド・スタブ
super.onRestart();
Log.d(TAG,"onRestart");
}
@Override
protected void onResume() {
// TODO 自動生成されたメソッド・スタブ
super.onResume();
Log.d(TAG,"onResume");
}
@Override
protected void onStart() {
// TODO 自動生成されたメソッド・スタブ
super.onStart();
Log.d(TAG,"onStart");
}
@Override
protected void onStop() {
// TODO 自動生成されたメソッド・スタブ
super.onStop();
Log.d(TAG,"onStop");
}
@Override
public void onClick(View v) {
// TODO 自動生成されたメソッド・スタブ
switch(v.getId()) {
case R.id.sub02_open_button:
//sub02へボタン押下
//Intentオブジェクト生成
Intent intent = new Intent(this,Sub02Activity.class);
//画面呼び出し
startActivity(intent);
//自画面終了
this.finish();
break;
case R.id.main_open_button:
//メニューボタン押下
//自画面終了
this.finish();
break;
}
}
}
●Sub02Activity.java
package com.example.activitytest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class Sub02Activity extends Activity implements OnClickListener{
private final String TAG = "Sub02Activity";
private Button sub01OpenButton = null; //sub01画面表示ボタン
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sub02);
Log.d(TAG,"onCreate");
this.sub01OpenButton = (Button)findViewById(R.id.sub01_open_button);
this.sub01OpenButton.setOnClickListener(this);
}
@Override
protected void onDestroy() {
// TODO 自動生成されたメソッド・スタブ
super.onDestroy();
Log.d(TAG,"onDestroy");
}
@Override
protected void onPause() {
// TODO 自動生成されたメソッド・スタブ
super.onPause();
Log.d(TAG,"onPause");
}
@Override
protected void onRestart() {
// TODO 自動生成されたメソッド・スタブ
super.onRestart();
Log.d(TAG,"onRestart");
}
@Override
protected void onResume() {
// TODO 自動生成されたメソッド・スタブ
super.onResume();
Log.d(TAG,"onResume");
}
@Override
protected void onStart() {
// TODO 自動生成されたメソッド・スタブ
super.onStart();
Log.d(TAG,"onStart");
}
@Override
protected void onStop() {
// TODO 自動生成されたメソッド・スタブ
super.onStop();
Log.d(TAG,"onStop");
}
@Override
public void onClick(View v) {
// TODO 自動生成されたメソッド・スタブ
switch(v.getId()) {
case R.id.sub01_open_button:
//sub01へボタン押下
//Intentオブジェクト生成
Intent intent = new Intent(this,Sub01Activity.class);
//画面呼び出し
startActivity(intent);
this.finish();
break;
}
}
}
●main.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Main"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="@+id/sub01_open_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sub01へ" />
<Button
android:id="@+id/app_end_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="終了" />
</LinearLayout>
</LinearLayout>
●sub01.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="sub01"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/main_open_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="mainへ"/>
<Button
android:id="@+id/sub02_open_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sub02へ"/>
</LinearLayout>
</LinearLayout>
●sub02.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="sub02"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/sub01_open_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sub03へ"/>
</LinearLayout>
</LinearLayout>
ではそれぞれの動作したときのサイクルを見ていきます。
●アプリ起動時
19:29:40.125: D/MainActivity: onCreate19:29:40.130: D/MainActivity: onStart
19:29:40.130: D/MainActivity: onResume
19:29:40.275: D/MainActivity: onCreateOptionsMenu
アプリのメイン画面が表示される。
●Main画面よりSub01へボタン押下時
19:30:27.380: D/MainActivity: onPause19:30:27.475: D/Sub01Activity: onCreate
19:30:27.475: D/Sub01Activity: onStart
19:30:27.475: D/Sub01Activity: onResume
19:30:27.810: D/MainActivity: onStop
Sub01が表示される
MainActivityはonStopになり後ろに積まれている状態
●Sub01画面よりSub02へボタン押下時
19:44:08.490: D/Sub01Activity: onPause19:44:08.570: D/Sub02Activity: onCreate
19:44:08.575: D/Sub02Activity: onStart
19:44:08.575: D/Sub02Activity: onResume
19:44:08.870: D/Sub01Activity: onStop
19:44:08.870: D/Sub01Activity: onDestroy
Sub02が表示される
●Sub02画面よりSub01へボタン押下時
19:45:55.680: D/Sub02Activity: onPause19:45:55.795: D/Sub01Activity: onCreate
19:45:55.795: D/Sub01Activity: onStart
19:45:55.795: D/Sub01Activity: onResume
19:45:56.105: D/Sub02Activity: onStop
19:45:56.105: D/Sub02Activity: onDestroy
Sub01が表示される
●Sub01画面よりMainへボタン押下時
19:46:33.815: D/Sub01Activity: onPause19:46:33.840: D/MainActivity: onRestart
19:46:33.840: D/MainActivity: onStart
19:46:33.840: D/MainActivity: onResume
19:46:34.110: D/Sub01Activity: onStop
19:46:34.110: D/Sub01Activity: onDestroy
アプリのメイン画面が表示される。
●Main画面より終了ボタン押下時
19:47:34.035: D/MainActivity: onPause19:47:34.705: D/MainActivity: onStop
19:47:34.705: D/MainActivity: onDestroy
●Sub01画面で端末のバックボタン押下時
19:50:15.410: D/Sub01Activity: onPause19:50:15.420: D/MainActivity: onRestart
19:50:15.420: D/MainActivity: onStart
19:50:15.420: D/MainActivity: onResume
19:50:15.700: D/Sub01Activity: onStop
19:50:15.700: D/Sub01Activity: onDestroy
アプリのメイン画面が表示される。
Mainへボタン押下時と同じ動きですね~(∩´∀`)∩
●Sub01画面で端末のホームボタン押下時
19:51:54.520: D/Sub01Activity: onPause19:51:55.150: D/Sub01Activity: onStop
端末のトップ画面が表示される。
からの~再開時
19:52:23.055: D/Sub01Activity: onRestart
19:52:23.055: D/Sub01Activity: onStart
19:52:23.055: D/Sub01Activity: onResume
Sub01が表示される
●検証結果
状態遷移する際にMein画面以外はFinish();を呼んでいるが、
Main画面以外での端末ボタン操作は、Sub画面のライフサイクル遷移となり、メイン画面のライフサイクル遷移は変わらない。
ちなみに画面遷移時にFinish();を呼ばずに状態遷移すると、表示した画面が終了せずに積み重なっておかしな動作になるので注意しましょう。
Main画面以外の画面を表示中は常にメイン画面が積まれている状態にするのが普通らしいです。
カテゴリーへ