onStop — AndroidライフサイクルにおけるActivityの非表示

著者: IT Sectr 公開日: 2026-03-04 読了時間: 9 分

onStop — AndroidのActivityライフサイクルのメソッドで、Activityがユーザーに表示されなくなったときにシステムによって呼び出されます。新しいActivityが完全にカバーした後、またはアプリが最小化されたときに、ActivityはStopped状態に移行します。onStopメソッドでは、開発者はアニメーションを停止し、カメラやセンサーのリソースを解放し、入力データの下書きを保存する必要があります。Android Vitals(Google、2025年)によると、onStopを適切に処理すると、アプリ最小化時のANR(アプリケーションが応答しない)の数が35%減少します。onStopの後、システムはonRestart(画面に戻る)またはonDestroy(完全な終了)を呼び出すことができます。Android DevelopersのActivityライフサイクルに関するドキュメントでは、onStopを可視状態と不可視状態の境界として説明しています。

重要なポイント

  • onStop — Activityの可視性が完全に失われたときに呼び出されるメソッドですが、Activityはまだメモリに残っています。
  • onStopの後、ActivityはStopped状態に移行します — メモリ上では生きていますが、表示されておらず、ユーザーと対話しません。
  • システムはActivityに戻るときにonRestart → onStart → onResumeを、終了時にonDestroyを呼び出すことができます。
  • onStopではリソースを解放する必要があります:アニメーションの停止、センサーとカメラの無効化、中間データの保存。
  • マルチタスクと最小化時のアプリの安定性には、onStopの正しい実装が重要な要素です。

AndroidにおけるonStopとは?

onStop — AppCompatActivityクラス(およびその前身のActivity)のコールバックメソッドで、Androidオペレーティングシステムによって、Activityがユーザーに完全に表示されなくなったときに呼び出されます。この時点で、Activityは別のActivity、ダイアログウィンドウ、システムランチャー、またはロック画面によって隠されています。ライフサイクルの観点から見ると、onStopはonPauseの後に続き、Activityオブジェクトとその状態はメモリに残っているものの、Activityが画面上に表示されなくなったことを示します。

ActivityがStopped(停止)状態に移行すると、RAMに状態を保持します — すべてのフィールド、View階層、ViewModelがアクセス可能なままです。これにより、StoppedはActivityが完全に削除されるDestroyed(破棄)状態と区別されます。システムUIは、メモリ不足時にStopped状態のアプリケーションプロセスを強制終了することがあります — これはいわゆるプロセス強制終了です。開発者は、プロセス強制終了時の復元を保証するために、onStopの前に呼び出されるonSaveInstanceState()に重要なデータ(下書き、スクロール位置)を保存する必要があります。

Android互換性定義ドキュメント(CDD)バージョン14+によると、Stopped状態のプロセスはOOM Killerによる強制終了の優先度が低くなります — バックグラウンドフェーズのプロセスよりは低いが、キャッシュされたプロセスよりは高いです。Googleの統計によると、68%のプロセス強制終了は、ActivityがPaused状態ではなくStopped状態のときに発生します。

onStopが呼び出されるタイミング:シナリオと順序

onStopはActivityが完全に可視性を失ったときに呼び出されます。理由は問いません:現在の上に新しいActivityを起動する、アプリを最小化する(ホームボタン)、画面をロックする、着信、またはシステムダイアログを開くなど。これらすべての場合で、Activityは最初にonPause(部分的なフォーカス喪失)を受け取り、次にonStop(完全な可視性喪失)を受け取ります。

onStop呼び出しの主なシナリオ:

  • 現在の上に新しいActivityを起動 — 現在のActivityはonPause、次にonStopを受け取ります。新しいActivityはonCreate → onStart → onResumeを経ます。
  • アプリの最小化(ホーム) — Activityは200~300ミリ秒でonPause → onStopに移行し、Stopped状態でメモリに残ります。
  • 画面のロック — ロック画面がActivityを完全に覆うため、システムはonPause → onStopを呼び出します。
  • 着信 — 電話アプリ(ダイヤラー)が前面に起動し、現在のActivityはonStopに移行します。
  • 別のアプリへの切り替え(最近のアプリ) — Activityは非表示になり、onStopを受け取りますが、プロセスキャッシュに残ります。

画面回転時にはonStopは呼び出されないことを理解することが重要です — この場合、Activityは破棄(onPause → onStop → onDestroy)され、再作成(onCreate → onStart → onResume)されます。例外はマニフェストのandroid:configChanges="orientation"フラグで、Activityの再作成を防ぎ、代わりにonConfigurationChanged()を呼び出します。

ActivityライフサイクルにおけるonStop

onStopは、Activityライフサイクルシーケンスの中で、可視状態と不可視状態の間の中心的な位置を占めます。完全なシーケンス:onCreate → onStart → onResume →(アクティブ状態)→ onPause → onStop → onDestroy(または復帰時にonRestart → onStart → onResume)。

状態メソッド可視性操作メモリ
CreatedonCreateなしなし割り当て済み
StartedonStart部分的なし完全
ResumedonResume完全あり完全
PausedonPause部分的なし完全
StoppedonStopなしなし完全*
DestroyedonDestroyなしなし解放済み

*Stopped状態では、Activityはメモリに保持されますが、リソース不足時にシステムによって強制終了される可能性があります。Stoppedプロセスの強制終了優先度は最後から2番目で、キャッシュされた空のプロセスのみが下です。

onStopとonSaveInstanceState: システムは動的UI状態を保存するために、onStopの前にonSaveInstanceState(Bundle)を呼び出します。開発者はこのメソッドをオーバーライドして、入力フィールドの値、RecyclerViewの位置、選択されたアイテムをBundleに保存します。Activityが破棄されない場合でも(ユーザーが単に最小化して戻った場合)、Bundleは構成変更時にonCreateに渡されます。Googleは、Activityの外部に存在するリポジトリデータやViewModelではなく、一時的なUI状態のみを保存することを推奨しています。

onStopで解放すべきリソース

onStopでは、Activityが表示されていないときに不要なすべてのリソースを開発者が解放する必要があります。これにより、バッテリー、CPU、メモリの負荷が軽減され、アクティビティに戻る際のANRも防止されます。

onStopで解放するもの:

  • アニメーションとトランジション — ObjectAnimator、ValueAnimator、ViewPropertyAnimatorを停止します。非表示のActivityで実行中のアニメーションはGPUサイクルを無駄にします。
  • センサー — SensorManager(加速度計、ジャイロスコープ、磁力計)の登録を解除します。Activityが非表示でもセンサーは電力を消費します。
  • カメラとマイク — Camera2またはCameraXを解放し、MediaRecorderを停止します。Activityが非表示の状態でカメラをアクティブにすることは、Google Playポリシーで禁止されています。
  • LocationListener — FusedLocationProviderClientまたはLocationManagerの登録を解除します。位置情報は最も電力を消費するリソースです。
  • ネットワークリスナー — WebSocketを閉じ、バックグラウンドで不要なHTTPリクエストをキャンセルします。
  • MediaPlayerとExoPlayer — バックグラウンドで再生を続けるべきでない場合は、一時停止または停止します。

onStopでやってはいけないこと: 長時間の操作(データベースへの大量データ保存、ネットワークリクエスト、複雑な計算)は実行しないでください。onStopはメインスレッドで実行され、Activityへの復帰をブロックします。長時間の操作には、遅延付きのWorkManagerまたはviewModelScopeのコルーチンを使用してください。ViewModelのリソースは解放しないでください — ViewModelはonStopを生き残り、復帰時に使用されます。

onStopとonPauseの違い

onPauseとonStopは、可視性喪失の程度と必須アクションの範囲が異なります。onPauseは部分的なフォーカス喪失時(ダイアログウィンドウやシステムメニューを開くなど)に呼び出され、onStopは完全な可視性喪失時に呼び出されます。この違いは、各段階でどのリソースを解放するかを選択する上で重要です。

特性onPauseonStop
可視性レベル部分的に可視完全に不可視
フォーカス喪失喪失
実行時間最大500ミリ秒最大5秒(ANRタイムアウト)
解放するリソース重要なもの(メディア、カメラ)すべての不可視リソース(センサー、アニメーション、位置情報)
復元onResumeonRestart → onStart → onResume
プロセス優先度高(フォアグラウンド)中(バックグラウンド)

一般的なルール:onPauseでは、別のアプリのユーザーエクスペリエンスに即座に影響を与えるシステムリソース(カメラ、メディアプレーヤー)を解放します。onStopでは、Activityが非表示のときに不要なその他すべてのリソースを解放します。Googleは、素早い切り替え時にonStopが呼び出されない可能性があるため、onPauseで重要なユーザーデータ(メールの下書き、設定)を保存することを推奨しています。

onStop → onRestart:画面に戻る

ユーザーが非表示のActivityに戻ると、システムはonRestart → onStart → onResumeを呼び出します。onRestartメソッドは、ActivityがStopped状態から戻ってきていることを示します。これは、onStopで解放されたUIとリソースを復元するための重要な段階です。

復帰時の呼び出しシーケンス:

  • onRestart() — Activityが再び表示されることが通知されます。典型的なアクション:データの再読み込み、リストの更新。
  • onStart() — Activityは表示されますが、まだアクティブではありません。ここでonStopで解放されたリソースが再初期化されます。
  • onResume() — Activityがフォーカスを取得し、操作の準備が整います。アニメーションが開始され、センサーが登録されます。

アプリケーションプロセスがStopped状態でシステムによって強制終了された場合、onRestartの代わりにonCreateが呼び出され、onSaveInstanceStateからのBundleが状態復元のために渡されます。このシナリオ(プロセス強制終了)はAndroidアプリのバグの最も一般的な原因の1つです。開発者はonRestartを実装しても、プロセス強制終了後のonCreateによる復元を考慮するのを忘れてしまいます。

KotlinでのonStopのコード例

例1:センサー解放を伴う基本的なonStop実装

Activity非表示時の正しいセンサー登録解除とアニメーション停止を示します。画面に戻ると、onStartでリソースが復元されます。

kotlin
class MainActivity : AppCompatActivity() {
    private lateinit var sensorManager: SensorManager
    private var accelerometer: Sensor? = null
    private var rotationAnimator: ObjectAnimator? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
    }

    override fun onStart() {
        super.onStart()
        accelerometer?.let {
            sensorManager.registerListener(sensorListener, it, SensorManager.SENSOR_DELAY_NORMAL)
        }
        rotationAnimator = ObjectAnimator.ofFloat(findViewById(R.id.icon), "rotation", 0f, 360f)
        rotationAnimator?.apply {
            duration = 3000
            repeatMode = ValueAnimator.RESTART
            repeatCount = ValueAnimator.INFINITE
            start()
        }
    }

    override fun onStop() {
        super.onStop()
        sensorManager.unregisterListener(sensorListener)
        rotationAnimator?.cancel()
    }

    override fun onRestart() {
        super.onRestart()
        Log.d("MainActivity", "ActivityがStopped状態から復帰")
    }

    private val sensorListener = SensorEventListener { event, _ ->
        Log.d("MainActivity", "加速度: x=${event.values[0]}, y=${event.values[1]}, z=${event.values[2]}")
    }
}

コードはonStartで加速度計センサーを登録し、無限回転アニメーションを開始します。onStopでは、センサーが登録解除され、アニメーションがキャンセルされます — これにより、Activityが非表示のときのバッテリー消費を防ぎます。onRestart → onStartを経て戻った後、リソースが再作成されます。

例2:SavedStateHandleによる状態保存を伴うonStop

ViewModel + SavedStateHandleを使用する最新のアプローチ。手動のBundle操作なしで、onStop中にフォームデータが自動的に保存されます。

kotlin
class FormViewModel(
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {
    var email: String
        get() = savedStateHandle["email"] ?: ""
        set(value) { savedStateHandle["email"] = value }

    var message: String
        get() = savedStateHandle["message"] ?: ""
        set(value) { savedStateHandle["message"] = value }
}

class FormActivity : AppCompatActivity() {
    private val viewModel: FormViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_form)
        Log.d("FormActivity", "onCreate: email=${viewModel.email}")
    }

    override fun onStop() {
        super.onStop()
        Log.d("FormActivity", "onStop: データがSavedStateHandleに保存されました")
    }
}

SavedStateHandleは、onStopの前に呼び出されるonSaveInstanceStateの間に、自動的にBundleに値を保存します。画面回転やプロセス強制終了時も、データは損失なく復元されます。Googleは、直接のonSaveInstanceStateではなく、フォームや下書きにはSavedStateHandleを推奨しています。

例3:onStopでの操作のためのlifecycleScope

onStopへの移行中に非同期でデータを保存するための、コルーチンを使用したlifecycleScopeの利用。コルーチンはメインスレッドをブロックせずにIOディスパッチャで実行されます。

kotlin
class NoteActivity : AppCompatActivity() {
    private val noteRepository = NoteRepository()

    override fun onStop() {
        lifecycleScope.launch(Dispatchers.IO) {
            val text = findViewById<EditText>(R.id.note_content).text.toString()
            noteRepository.saveDraft(text)
            withContext(Dispatchers.Main) {
                Log.d("NoteActivity", "下書きがonStopで保存されました")
            }
        }
        super.onStop()
    }
}

lifecycleScope.launchコルーチンは、Activityのライフサイクルが終了すると自動的にキャンセルされます。Dispatchers.IOを使用することで、データベースやファイルへの書き込みがActivityへの復帰をブロックしないことが保証されます。Googleによると、lifecycleScopeのコルーチンは、onStopで非同期操作を実行する推奨される方法です。

よくある質問

onStopとonDestroyの違いは何ですか?

onStop — Activityは表示されなくなりますが、Stopped状態でメモリに残ります。システムはonRestartを介してActivityを復帰させることができます。onDestroy — Activityは破棄され、メモリが解放されます。onDestroy後は、新しいActivityインスタンス(onCreate)を作成することによってのみ復帰が可能です。

super.onStop()を呼び出すことは必須ですか?

はい、必須です。super.onStop()は、フラグメント、LoaderManager、ViewModelStoreなどのシステムコンポーネントの正しい動作を保証します。super.onStop()をスキップすると、メモリリークやフラグメントの復元ミスを引き起こす可能性があります。super.onStop()は常に最後または最初に呼び出してください — 順序は重要ではありませんが、呼び出しは必須です。

onStopが呼び出されたことを確認するには?

各ライフサイクルメソッドでLog.dまたはTimberを使用します。Activityのタグでlogcatフィルターを有効にします。本番環境ではAndroid Vitalsを使用します — Googleが自動的にライフサイクルメトリクスを収集し、Play Consoleで異常を表示します。ProcessLifecycleOwnerを介したライフサイクル監視も利用可能です。

onStopで例外がスローされるとどうなりますか?

onStopでキャッチされなかった例外は、アプリのForce Closeを引き起こします。システムはライフサイクルコールバックの例外をキャッチしません。onStopで例外をスローする可能性のある操作(ファイル操作、ネットワーク)を実行する場合は、try-catchでラップし、super.onStop()を中断せずにエラーをログに記録してください。

onStopでBitmapを解放する必要がありますか?

いいえ、Activity内のBitmapは、参照がなければGCによって収集されます。onStopでの強制解放(recycle())は不要であり、むしろ有害です — ActivityがonRestartで戻った場合、Bitmapを再読み込みする必要があります。画像の読み込みにはGlideまたはCoilを使用してください — これらのライブラリは自動的にキャッシュとライフサイクルを管理します。

まとめ

  • onStop — 完全な可視性喪失時に呼び出されるActivityライフサイクルメソッド。ActivityはStopped状態でメモリに残ります。
  • onStopの後、2つのシナリオが可能です:onRestart(画面に戻る)またはonDestroy(Activityの破棄)。
  • onStopでは、センサー、アニメーション、カメラ、位置情報リスナーなど、Activityが非表示のときに不要なものをすべて解放する必要があります。
  • onStopは可視性のレベルでonPauseと異なります:onPauseは部分的な喪失、onStopは完全な可視性喪失です。
  • onSaveInstanceStateはonStopの前に呼び出されます — 一時的なUI状態を保存するために使用します。
  • Dispatchers.IOを使用したlifecycleScopeコルーチン — onStopでの非同期操作の推奨方法です。
  • 常にsuper.onStop()を呼び出し、Force Closeを避けるために危険な操作をtry-catchでラップしてください。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください