Androidアーキテクチャコンポーネント(AAC)は「堅牢でテストとメンテナンスが簡単なアプリの設計を支援する」とドキュメントで説明されています。
その中で紹介されているコンポーネントの1つが「Lifecycle」です。
Lifecycleについて、まとめました。
目次
ラフサイクル対応コンポーネントとは
画面の表示制御以外にも、Activityのライフサイクルに連動させたい処理があります。
例えば、
センサーは画面の表示中のみ動作させればバッテリー容量の節約になる。
onStartで起動、onStopで停止すればよい。
レシーバは画面の表示中のみ受信させればプロセッサ資源の節約になる。
onStartでレシーバを登録、onStopで解除するばよい。
などです。
このような処理が多くなると、ライフサイクル中に雑多な処理が集中して、プログラムの見通しが悪くなります。
Lifecycleを実装すると、Activityがシステムから受け取るコールバックの起動イベント(図中のON_START,ON_STOP)を特定のクラスへ転送できるようになります。特定のクラス側はイベントを受け取って関数が起動できます。
これは「特定のクラスにライフサイクルを持たせる」ことを示します。このようなクラスを「ライフサイクル対応コンポーネント」と呼びます。
ラフサイクル対応コンポーネントがあれば、Activityのライフサイクル中に処理を置く必要はありません。代わりにコンポーネントのライフサイクル中へ置けば良いのです。
Activityは画面の表示のみに専念でき、プログラムがスッキリします。
Lifecycleの実装(イベントを転送する)
Lifecycleを実装してイベントを転送するためには、次の3つが必要です。
(1)LifecycleOwnerインターフェースを実装
(2)イベントの転送処理
(3)イベントの受信クラスの登録
Activityがandroidx.appcompat.app.AppCompatActivityを継承していれば、すでに(1)と(2)は実施済みです。特に何もする必要はなく、イベントが転送できる状態になっています。
(3)は後述します。
コンポーネント作成(イベントを受信する)
ライフサイクル対応コンポーネントはLifecycleObserverインターフェースを実装します。
LifecycleObserverは抽象プロパティも抽象関数も持たない空のインターフェースです。このクラスがエベントを受信する対象になっている事を示します。マーキングの役割です。
関数へ@OnLifecycleEventアノテーションを付加して、イベントによって起動する関数であることを指定します。
class SampleComponent : LifecycleObserver{ @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) fun onCreate() { // 引数なしタイプ // Createで行う処理 } @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) fun onCreate(owner: LifecycleOwner) { // LifecycleOwner引数あり合タイプ // Createで行う処理 } /* ** onStartも同様 Lifecycle.Event.ON_START ** onResumeも同様 Lifecycle.Event.ON_RESUME ** onPauseも同様 Lifecycle.Event.ON_PAUSE ** onStopも同様 Lifecycle.Event.ON_STOP ** onDestroyも同様 Lifecycle.Event.ON_DESTROY */ }
public interface LifecycleObserver { }
後は、「Lifecycle実装:(3)イベントの受信クラスの登録」で示したように、Lifecycle#addObserver( )を使ってコンポーネントを登録すれば、イベントが転送されるようになります。
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) lifecycle.addObserver(SampleComponent()) //(3)イベントの受信クラスの登録 ... } ... }
ライフサイクルのEventsとStates
Lifecycleはライブサイクルの状態をEventとState列挙型で管理しています。
下図は状態の変化とタイミングを示しています。
ライフサイクル対応コンポーネントに転送されるEventの発火とStateの変化は同時に起こります。
StateはLifecycleから取得できるので条件判断に役立ちます。
※後述「すべてに適合するイベント」を参照
すべてに適合するイベント(ON_ANY)
ON_ANYイベントはすべてに適合するイベントです。
よって、@OnLifecycleEventアノテーションにON_ANYが指定されている関数は、すべてのEventで実行されます。
class SampleComponent : LifecycleObserver{ @OnLifecycleEvent(Lifecycle.Event.ON_ANY) // すべてのイベントを受信 fun onAny() { // すべてのEventで行う処理 } @OnLifecycleEvent(Lifecycle.Event.ON_ANY) fun onAny(owner: LifecycleOwner) { when(owner.lifecycle.currentState) { // LifecycleからStateを取得 Lifecycle.State.STARTED, Lifecycle.State.RESUMED -> { // STARTEDとRESUMEDで行う処理 } else -> { // その他のStateで行う処理 } } } @OnLifecycleEvent(Lifecycle.Event.ON_ANY) fun onAny(owner: LifecycleOwner, event: Lifecycle.Event) { when(event) { Lifecycle.Event.ON_START, Lifecycle.Event.ON_RESUME -> { // ON_STARTとON_RESUMEで行う処理 } else -> { // その他のEventで行う処理 } } } }
コンポーネントを複数登録
複数のコンポーネントにイベントを転送したい場合は、コンポーネントの数だけLifecycle#addObserver( )を実行すればよいです。
ただし、登録した順番にイベントが転送されます。
class AAA_Sensor : LifecycleObserver { ... @OnLifecycleEvent(Lifecycle.Event.ON_START) fun onStart() { Log.i(TAG, "onStart Start") // センサーの起動 Log.i(TAG, "onStart End") } /* onStopも同様 Lifecycle.Event.ON_STOP */ ... }
class BBB_Sensor : LifecycleObserver { ... @OnLifecycleEvent(Lifecycle.Event.ON_START) fun onStart() { Log.i(TAG, "onStart Start") // センサーの起動 Log.i(TAG, "onStart End") } /* onStopも同様 Lifecycle.Event.ON_STOP */ ... }
class CCC_Receiver : LifecycleObserver { ... @OnLifecycleEvent(Lifecycle.Event.ON_START) fun onStart() { Log.i(TAG, "onStart Start") // レシーバの登録 Log.i(TAG, "onStart End") } /* onStopも同様 Lifecycle.Event.ON_STOP */ ... }
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { ... lifecycle.addObserver(AAA_Sensor()) lifecycle.addObserver(BBB_Sensor()) lifecycle.addObserver(CCC_Receiver()) } override fun onStart() { super.onStart() Log.i(TAG, "onStart Start state=${lifecycle.currentState}") Thread.sleep(100) Log.i(TAG, "onStart End state=${lifecycle.currentState}") } /* onStopも同様 */ ... }
[ アプリを起動 ] I/MainActivity: onStart Start state=CREATED I/MainActivity: onStart End state=CREATED I/AAA_Sensor: onStart Start I/AAA_Sensor: onStart End I/BBB_Sensor: onStart Start I/BBB_Sensor: onStart End I/CCC_Receiver: onStart Start I/CCC_Receiver: onStart End [ アプリを終了 ] I/CCC_Receiver: onStop Start I/CCC_Receiver: onStop End I/BBB_Sensor: onStop Start I/BBB_Sensor: onStop End I/AAA_Sensor: onStop Start I/AAA_Sensor: onStop End I/MainActivity: onStop Start state=CREATED I/MainActivity: onStop End state=CREATED
関連記事: