Androidアーキテクチャコンポーネント(AAC)は「堅牢でテストとメンテナンスが簡単なアプリの設計を支援する」とドキュメントで説明されています。
その中で紹介されているコンポーネントの1つが「Lifecycle」です。
Lifecycleについて、まとめました。
【注意】
androidx.lifecycle:lifecycle-*:2.4.0以降は、@OnLifecycleEventが非推奨となり、DefaultLifecycleObserverを使った記述が推奨になっています。
※詳細は「ライフサイクル対応コンポーネント作成(DefaultLifecycleObserverを使用)」を参照
目次
ラフサイクル対応コンポーネントとは
画面の表示制御以外にも、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
関連記事:
