Activity Lifecycleとは、AndroidがActivityの状態遷移(作成、表示、入力フォーカス、部分的な表示喪失、完全な非表示、破棄)に伴って呼び出す一連のコールバックメソッドです。システムは、onCreate()が呼び出された瞬間からonDestroy()に至るまで、アプリケーションの各画面のライフサイクルを管理します。これらの状態を理解することは、Androidアプリケーションの安定動作に必須の要件であり、メソッド間の遷移を誤って処理すると、メモリリーク、ユーザーデータの損失、予期しないクラッシュを引き起こします。Androidアーキテクチャの詳細については、Androidに関する一般的な記事をお読みください。
重要なポイント
Activity Lifecycle(アクティビティライフサイクル)とは、Androidアプリケーションの各画面が作成から完全な破棄に至るまでに通過する状態機械です。Androidシステムは、ユーザーの操作(アプリケーションの起動、最小化、画面回転、着信応答、アプリケーションの切り替え、終了)に基づいてこのプロセスを管理します。
ライフサイクルの理解はすべてのAndroid開発者にとって不可欠です。システムはメモリ不足時にいつでもActivityを破棄する可能性があり、アプリケーションは状態を正しく復元する必要があるからです。Google Android Vitals(2025)によると、onSaveInstanceState()で状態保存を処理しないアプリケーションは、Activity再作成時に42%多くのクラッシュを示します。
ライフサイクルには6つの主要なコールバックメソッドが含まれます:onCreate()、onStart()、onResume()、onPause()、onStop()、onDestroy()。さらに、Activityが停止状態から戻る際にonStart()の前に呼び出されるonRestart()メソッドもあります。各メソッドには厳密に定義された目的と実行時間があり、システムはこれらを順次呼び出し、開発者は任意のメソッドをオーバーライドして独自のロジックを実装できます。
サイクルは3つの主要な段階に分けられます:全ライフタイム(onCreate → onDestroy)、可視ライフタイム(onStart → onStop)、フォアグラウンドライフタイム(onResume → onPause)。これら3つのレベルを理解することで、初期化コードとリソース解放コードを適切に分散できます。
各ライフサイクルメソッドは厳密に定義されたタスクを実行します。システムはこれらを固定された順序で呼び出し、開発者は特定のロジックに必要なメソッドのみをオーバーライドする必要があります。ライフサイクルメソッドを直接呼び出すことは推奨されません。これはAndroid Runtimeが処理します。
アプリケーション起動時の一般的な順序:onCreate → onStart → onResume。戻るボタンを押した場合:onPause → onStop → onDestroy。最小化した場合:onPause → onStop、その後復帰時:onRestart → onStart → onResume。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
}
override fun onPause() {
super.onPause()
}
override fun onStop() {
super.onStop()
}
override fun onDestroy() {
super.onDestroy()
}
override fun onRestart() {
super.onRestart()
}
}
オーバーライドされた各メソッドはsuperバージョンを呼び出す必要があります。これがないと、システムは状態遷移を正しく完了できません。このルールはAndroid Developersのドキュメントに定められており、Android Studioのlintルールでチェックされます。
第1レベル — 全ライフタイム:onCreateとonDestroyの間の期間。ここで1回限りの初期化とグローバルリソースの最終解放が行われます。第2レベル — 可視ライフタイム:onStartとonStopの間。Activityは画面上に表示されますが、別のウィンドウで部分的に覆われる可能性があります。第3レベル — フォアグラウンドライフタイム:onResumeとonPauseの間。Activityはタスクスタックの最上位にあり、ユーザーと対話します。
onCreate() — Activityライフサイクルの最初で唯一の必須メソッド。システムはActivityインスタンスを作成する際に1回呼び出します。このメソッドはsavedInstanceState: Bundle?パラメータを受け取り、Activityが破棄後に再作成される場合(画面回転時など)、以前に保存された状態が含まれます。
onCreate内では以下のタスクが実行されます:setContentView()によるレイアウトリソースを使用したユーザーインターフェースの初期化、findViewById()によるView要素のバインド、RecyclerViewやViewPagerのアダプター設定、savedInstanceStateからの状態復元、ViewModelとLiveDataの初期化、クリックやジェスチャーリスナーの設定。メソッドは可能な限り迅速に完了する必要があります。ここでの長時間操作は最初のフレームのレンダリングをブロックし、アプリケーションの起動時間を増加させます。
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_profile)
val userNameText: TextView = findViewById(R.id.user_name)
val loadButton: Button = findViewById(R.id.load_button)
if (savedInstanceState != null) {
userNameText.text = savedInstanceState.getString("user_name")
}
loadButton.setOnClickListener {
loadUserProfile()
}
}
Activityが初めて作成される場合、savedInstanceStateはnullです。画面回転後に再作成される場合、BundleにはonSaveInstanceState()で保存されたデータが含まれます。nullチェックは、ユーザーが入力したデータを失うことなくUIを正しく復元するための標準的なプラクティスです。
onStart()は、Activityがユーザーに表示可能になったときに、onCreate()の直後またはonRestart()の後に呼び出されます。この状態では、Activityはまだフォアグラウンドになくユーザーと対話できませんが、ユーザーインターフェースはすでに画面上に表示されています。例えば、アプリケーション起動時、システムはonStartとonResumeの呼び出しの間にインターフェースの最初のフレームをレンダリングします。
onStartメソッドでは通常、以下のアクションが実行されます:Activityが表示されている間動作するアニメーションの開始、BroadcastReceiverのバインド、位置情報サービスやセンサーへの接続、ViewModelやRoomからのデータ更新。アプリケーションがプロセス内でクライアント・サーバーアーキテクチャを使用している場合、bindService()によるBoundサービスへのバインドもここで行われます。
override fun onStart() {
super.onStart()
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
5000L,
10f,
locationListener
)
}
override fun onStop() {
super.onStop()
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
locationManager.removeUpdates(locationListener)
}
重要なルール:onStartで接続したリソースはonStopで解放する必要があります。これにより、Activityが画面に表示されていないときにバッテリーやシステムリソースを消費しないことが保証されます。Google Play Storeはアップデートの審査時に、LocationListenerやその他のシステムサービスのリークをチェックします。
onResume() — Activityがフォアグラウンドにあり、ユーザーと対話する準備ができている状態。これが画面の動作状態です。システムは入力フォーカスをActivityに移し、すべてのタッチイベント、キーボード入力、ジェスチャーがこの画面に送られます。onResumeメソッドは、Activityがフォアグラウンドに戻るたび(別のActivityが終了した後、ダイアログが閉じられた後、デバイスのロックが解除された後)に呼び出されます。
onResumeでは以下が実行されます:onPauseで一時停止されたアニメーションの再開、カメラやその他の排他リソースのオープン、センサーリスナー(加速度計、ジャイロスコープ)の登録、UIのタイマーとストップウォッチの開始、現在のデータによる画面内容の更新。onResume/onPauseのペアは、フォーカスがある場合にのみアクティブにする必要があるリソース(継続的な音声認識やビデオキャプチャなど)に使用されます。
override fun onResume() {
super.onResume()
cameraHolder.openCamera()
animator.resume()
sensorManager.registerListener(
stepCounter,
sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER),
SensorManager.SENSOR_DELAY_NORMAL
)
}
override fun onPause() {
super.onPause()
cameraHolder.closeCamera()
animator.pause()
sensorManager.unregisterListener(stepCounter)
}
onStartとonResumeの違いは重要です。Activityは表示されていても(onStart)、アクティブでない(onResume)場合があります。例えば、ポップアップダイアログや透明なロック画面が上に表示されている場合です。排他アクセスを必要とする排他リソースは、onStartではなくonResumeで開く必要があります。
onPause()は、Activityが入力フォーカスを失ったものの、部分的に表示されたままの場合に呼び出されます。典型的なシナリオ:ダイアログボックスの表示、最近使ったアプリボタンの押下、着信、ホームボタンの押下(この場合、onPauseの後にonStopが続きます)。onPauseメソッドは、ユーザーが失ってはならないデータを保存する最後の信頼できる場所です。
onPauseでは以下が実行されます:メールの下書きや入力フォームのRoomやSharedPreferencesへの保存、アニメーションやビデオ再生の停止、カメラのクローズと排他リソースの解放、バックグラウンドで重要でない高コスト操作のキャンセル。onPauseメソッドは100ミリ秒未満で完了する必要があります。システムはonPauseが制御を返すまで次のActivityへの遷移をブロックし、制限を超えるとANR(Application Not Responding)が発生します。
override fun onPause() {
super.onPause()
val editor = SharedPreferences.Manager ...
editor.putString("draft_text", draftEditText.text.toString())
editor.apply()
videoView.pause()
cameraHolder.release()
}
重要:onPauseはUIスレッドで実行されるため、Roomを使用した同期的なデータベース書き込みなどのブロッキング操作は、非同期操作(コルーチン)に置き換えるか、バックグラウンドスレッドで実行する必要があります。SharedPreferencesにはcommit()ではなくapply()を使用してください。applyは非同期的にデータを書き込み、UIスレッドをブロックしません。
onStop()は、Activityがユーザーに表示されなくなったときに呼び出されます。これは以下の場合に発生します:Activityが別のActivityに完全に覆われた、ユーザーがホームボタンを押したか別のアプリケーションに切り替えた、Activityが終了している(その後onDestroyが呼び出されます)。onStop状態では、Activityはメモリに残り、すべてのフィールドを保持します。破棄されてはいませんが、アクティブでもありません。
onStopでは以下が実行されます:onStartで登録したBroadcastReceiverの登録解除、Boundサービスからの切断、LocationListener、SensorListener、その他のシステムリスナーの解放、アプリケーションが非表示のときに不要な長時間バックグラウンド操作の停止、onPauseで行われなかった場合のonSaveInstanceState()によるBundleへの現在のUI状態の書き込み。
override fun onStop() {
super.onStop()
unregisterReceiver(connectivityReceiver)
unbindService(serviceConnection)
if (isChangingConfigurations()) {
Log.d("Lifecycle", "設定によりActivityが再作成されます")
}
}
システムはメモリ不足時に、onDestroyを呼び出さずにonStop状態のActivityを破棄することがあります。そのため、すべての重要なデータはonStopへの移行前に保存する必要があります。isChangingConfigurations()フラグは、onStop呼び出しが画面回転に関連しているかどうかを判断するのに役立ちます。この場合、Activityは終了ではなく再作成されます。
onDestroy() — Activityが完全に破棄される前に呼び出される最後のライフサイクルメソッド。システムは2つのケースでonDestroyを呼び出します:Activityがfinish()で終了するかユーザーが戻るボタンを押した場合、Activityが設定変更(画面回転など)によりシステムによって破棄され再作成される場合。onDestroyメソッドでは、スレッドやコルーチンのバインド解除、永続的に開かれたカーソルやソケットのクローズ、NDKを介したネイティブメモリの解放など、最終的なリソースクリーンアップを実行できます。
override fun onDestroy() {
super.onDestroy()
backgroundJob.cancel()
dbHelper.close()
if (isFinishing) {
Log.d("Lifecycle", "Activityが完全に終了しています")
} else {
Log.d("Lifecycle", "Activityが再作成されます")
}
}
重要な注意:アプリケーションプロセスがシステムによって強制終了された場合(out-of-memory kill)、onDestroyは呼び出される保証がありません。そのため、データ保存をonDestroyに依存することはできません。このタスクはonPauseまたはonStopで処理します。isFinishingプロパティは、finish()によるActivityの終了と設定変更による再作成を区別するのに役立ちます。
onRestart()は、Activityが停止状態(onStop)からフォアグラウンドに戻る際に、onStart()の前に呼び出されます。これは、ユーザーが最近使ったアプリメニューからアプリケーションを再度開いたり、子画面で戻るボタンを押してActivityに戻ったりする場合に発生します。onRestartメソッドでは、onCreateとは異なるロジックを実行できます。例えば、Activityが非表示の間に変更された可能性のあるデータを更新できます。
override fun onRestart() {
super.onRestart()
refreshDataFromNetwork()
Log.d("Lifecycle", "Activityがスタックから再起動しています")
}
典型的なシナリオ:ユーザーがアプリケーションを開き、別のタスクに切り替え、1時間後に戻ってきました。onRestartでは、アプリケーションはデータの最新性を確認し、長時間経過している場合はコンテンツの再読み込みを提案できます。これによりユーザーエクスペリエンスが向上し、古い情報が表示される可能性が低減します。
画面回転はActivity再作成の最も一般的なシナリオです。デフォルトでは、Androidは向きが変わるたびに現在のActivityを破棄し、新しいものを作成します。状態を保存しない場合、ユーザーは入力したすべてのデータを失います。Androidはこれに対して2つのメカニズムを提供します:シリアライズ可能なデータ用のonSaveInstanceState()と、設定変更を生き延びるデータ用のViewModelです。
一時的な状態を保存するために、Activityが破棄される前にonSaveInstanceState()が呼び出されます。保存されたデータは、savedInstanceStateパラメータを介してonCreateと、onStart後に呼び出されるonRestoreInstanceState()メソッドに渡されます。Bundleにはサイズ制限(約500KB)があるため、大量のデータ(ビットマップなど)はViewModelを介して保存します。
<!-- AndroidManifest.xml — 向きの固定 -->
<activity android:name=".MainActivity"
android:configChanges="orientation|screenSize" />
android:configChangesによる向きの固定はActivityの再作成を防ぎますが、アプリケーションが両方の向きをサポートする必要がある場合はアンチパターンと見なされます。Googleの最新の推奨は、ユーザーがUIに入力するデータに対して、onSaveInstanceStateと組み合わせてViewModelを使用することです。
Fragmentには独自のライフサイクルがあり、Activityと似ていますが、追加のメソッドがあります:onAttach、onCreate、onCreateView、onViewCreated、onStart、onResume、onPause、onStop、onDestroyView、onDestroy、onDetach。Fragmentは常にActivity内に存在し、そのライフサイクルはコンテナActivityのライフサイクルに結びついています。Activityが破棄されると、Fragmentもそれに従います。
主な違い:Fragmentはコンポーネントの状態だけでなく、View階層も管理します。onCreateViewメソッドはFragmentのルートViewを返し、onDestroyViewはこの階層を破棄します。これにより、Fragmentは画面回転時のActivity再作成を生き延びることができます。Fragmentは保持され、そのViewはonCreateViewで再作成されます。
class ProfileFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.fragment_profile, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val avatarImage: ImageView = view.findViewById(R.id.avatar_image)
loadAvatar(avatarImage)
}
}
onCreateとonCreateViewの違いを理解することは非常に重要です。onCreateはFragmentのライフタイムで1回(Viewが再作成される場合でも)呼び出されますが、onCreateViewはFragmentがView階層を作成または再作成するたびに呼び出されます。データの初期化はonCreateで行われ、UIのバインドはonViewCreatedで行われます。
LifecycleObserver — ActivityやFragmentのメソッドをオーバーライドせずにライフサイクルの変更に反応できるAndroid Jetpackライブラリのコンポーネント。各ライフサイクルメソッドでコードを重複させる代わりに、開発者は@OnLifecycleEventアノテーションを持つ別のクラスを作成し、それをlifecycle.addObserver()に渡します。
JetpackはLifecycleOwnerインターフェースも提供しており、AppCompatActivityとFragmentがこれを実装しています。LifecycleOwnerを実装する任意のオブジェクトは、LiveDataのサブスクリプション、lifecycleScopeを介したコルーチン、ライフサイクルに関連したWorkManagerを管理できます。これはMVVMとJetpackに基づくモダンなAndroidアーキテクチャの基盤です。
class MyLocationObserver(private val context: Context) : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
startLocationUpdates()
}
override fun onStop(owner: LifecycleOwner) {
stopLocationUpdates()
}
}
// Activity内:
lifecycle.addObserver(MyLocationObserver(this))
DefaultLifecycleObserverの使用は、テストを簡素化し、コードの重複を減らし、ライフサイクルロジックを異なる画面間で再利用可能にします。これは、各Activityで手動でonStart/onStopをオーバーライドする現代的な代替手段です。IT Sectrが開発したAndroidアプリケーションでは、位置情報、Bluetoothスキャン、分析にLifecycleObserverを適用しています。これにより、ボイラープレートコードの量が30〜40%削減されます。
よくある質問
super.onCreate()やその他のsuperライフサイクルメソッドを呼び出さない場合、システムはSuperNotCalledExceptionをスローし、アプリケーションはクラッシュします。これはAndroid Runtimeの厳格な要件です。各メソッドは基本クラスに実行を委譲する必要があり、そうしないと内部状態機械が次の状態に遷移できません。
画面回転時にActivityが再作成されるのは、向きの変更がデバイスの設定変更であるためです。デフォルトでは、Androidは代替リソース(layout-land、values-land)を読み込むためにActivityを破棄し、新しいものを作成します。再作成を無効にするには、マニフェストにandroid:configChanges属性を追加できますが、Googleはデータを保持するためにViewModelを使用することを推奨しています。
重要なデータはonPause()で保存します。これは、アプリケーションがシステムによって強制終了される前に呼び出されることが保証されている最後のメソッドだからです。onStopとonDestroyの後、システムは追加のメソッドを呼び出さずにプロセスを終了できます。下書きや中間データには、apply()を使用したSharedPreferences、またはコルーチンを使用したRoomを使用してください。
onPauseは、Activityがフォーカスを失ったものの、部分的に表示されたままの場合(ダイアログボックスが開かれた場合など)に呼び出されます。onStopは、Activityが別のActivityやホームボタンの押下によって画面から完全に非表示になった場合に呼び出されます。主な実用的な違い:onPauseはデータ保存の最後のポイント、onStopはバックグラウンドで不要なリスナーやシステムサービスを解放する場所です。
ViewModelは、UIデータを保存し、設定変更(画面回転)を自動的に生き延びるAndroid Jetpackコンポーネントです。ViewModelはActivityの再作成時に破棄されません。LifecycleOwner(ActivityまたはFragment)が完全に終了するまで存続します。これにより、BundleやonSaveInstanceStateを使用せずに、画面回転時のデータ保存の問題を解決します。ViewModelはGoogleが推奨するMVVMアーキテクチャの必須要素です。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。