Android Kotlin基礎講座 04.2: 複雑なライフサイクル状態
目次
タスク:Android lifecycleライブラリを使う
DessertClickerアプリにおいて、onStart()の中でタイマーを起動した場合、onStop()中でタイマーを停止する必要があるということは容易に理解できたはずです。先ほどはたった一つのタイマーしかなかったため、タイマーを停止するのを覚えておくことは容易でした。
さらに複雑なAndroidアプリにおいては、onStart()やonCreate()の中でよりたくさんのものをセットアップし、それら全てをonStop()やonDestroy()の中で破棄することになります。例としては、セットアップと破棄、およびスタートと停止が必要なものにはアニメーション、音楽、センサー、タイマーなどがあります。もし一つでも忘れた場合、バグの原因となりえます。
Android Jetpackの一部であるlifecycleライブラリでは、この処理を簡単にすることができます。このライブラリはたくさんの動きのあるパーツをトラックする必要があり、それらが異なるライフサイクル状態の中にあるときに特に便利です。
通常はアクティビティやフラグメントはコンポーネント(DessertTimerなど)に対して、ライフサイクルコールバックが起こるときに何をすべきかを伝達します。しかし、lifecycleライブラリを使うと、コンポーネント自身がライフサイクルの変化を確認し、変化に応じて必要な動作を行ってくれます。
lifecycleライブラリには以下の三つの主要パートがあります。
- ライフサイクルオーナー:これはライフサイクルを持つコンポーネントです。
アクティビティやフラグメントはライフサイクルオーナーです。ライフサイクルオーナーはLifecycleOwnerインターフェースを実装します。 - Lifecycleクラス:これはライフサイクルオーナーの実際の状態を保持し、ライフサイクルが変化したときにイベントを起こすクラスです。
- ライフサイクルオブザーバー:これはライフサイクル状態を監視し、ライフサイクルが変化したときに処理を実行します。ライフサイクルオブザーバーはLifecycleObserverインターフェースを実装します。
このタスクでは、DessertClickerアプリをAndroid lifecycleライブラリを使うように変換していき、ライブラリがどのようにしてアクティビティやフラグメントのライフサイクルの管理を容易にしてくれるのかを学習していきます。
ステップ1:DessertTimerをライフサイクルオブザーバーにする
lifecycleライブラリのキーパートはライフサイクルオブザベーションという概念です。オブザベーション(監視)はクラス(DessertTimerなど)にアクティビティやフラグメントについて知り、それらの状態の変化に対応してそれら自身をスタート・ストップさせることを可能にします。ライフサイクルオブザーバーを用いることで、アクティビティやフラグメントのメソッドからスタート・ストップ用のオブジェクトの必要性を排除することができます。
- DessertTime.ktクラスを開いてください。
- クラス宣言文を以下のように変更してください。
class DessertTimer(lifecycle: Lifecycle) : LifecycleObserver {
この新しいクラス定義では以下の二つのことをしています:
- コンストラクタはLifecycleオブジェクトをとっています。これはタイマーが監視しているライフサイクルです。
- クラス定義はLifecycleObserverインターフェースを実装しています。
- runnable変数の下に、クラス定義に対するinitブロックを追加してください。initブロックの中で、addObserver()メソッドを使ってオーナー(アクティビティ)から渡されたライフサイクルオブジェクトをこのクラス(オブザーバー)に接続してください。
init {
lifecycle.addObserver(this)
}
- @OnLifecycleEventによってstartTimer()をアノテーションしてください。ON_STARTライフサイクルイベントを使用してください。ライフサイクルオブザーバーが監視できる全てのライフサイクルイベントはLifecycle.Eventクラスの中にあります。
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun startTimer() {
- 同じことをstopTime()にも施してください。ライフサイクルイベントはON_STOPです。
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun stopTimer()
ステップ2:MainActivityの修正
MainActivityクラスは既に継承を通してライフサイクルオーナーになっています。なぜならFragmentActivityというスーパークラスはLifecycleOwnerを実装しているからです。従って、アクティビティをライフサイクルオーナーにするためのしなければならないことはありません。しなければならないことはアクティビティのライフサイクルオブジェクトをDessertTimerコンストラクタに渡すことだけです。
- MainActivityを開いてください。onCreate()メソッドの中のDessertTimerの初期化を修正してthis.lifecycleを含ませてください。
dessertTimer = DessertTimer(this.lifecycle)
アクティビティのlifecycleプロパティはこのアクティビティが所有するLifecycleオブジェクトを保持しています。
- onCreate()中のstartTimer()の呼び出し、onStop()中のstopTimer()の呼び出しを削除してください。DessertTimerは現在ライフサイクルを自身で監視し、ライフサイクル状態が変化したときに自動で知ることができるので、DessertTimerに何をするべきかをアクティビティから伝える必要はありません。これらのコールバック中でしていることはログメッセージの表示だけです。
- コンパイルしてアプリを起動してください。Logcatを開き、予期した通りにタイマーが起動していることを確認してください。
- ホームボタンをタップしてアプリをバックグラウンドにおいてください。予期した通りにタイマーが停止していることを確認してください。