【Kotlin/Android Studio】Handlerの使い方!遅延や周期で処理を繰り返す方法

この記事からわかること
- Android Studio/KotlinのHandlerの使い方
- MessageQueueやRunnable、Looperの役割と違い
- カウントアップタイマーの実装方法
- 遅延処理:postDelayedメソッド
- スレッド操作
index
[open]
\ アプリをリリースしました /
環境
- Android Studio:Flamingo
- Kotlin:1.8.20
Handlerとは?
AndroidのHandler
とはスレッドと非同期で実行される処理に関連するタスクを管理するためのクラスです。Handler
を使用することでタイマーの設定や非同期的なタスクの処理、UIに関する作業をサブスレッドで行いたい場合などさまざまな機能を実現することができます。
Handler
を理解するためにはMessageQueue
やRunnable
オブジェクト、Looper
の存在が重要になってきます。
- Handler:スレッド間通信や非同期タスクを管理する役割
- MessageQueue:キュー構造でタスクを管理している場所
- Runnable:実行されるタスクの単位
- Looper:スレッド内でMessageQueueを管理し処理を実行する役割
MessageQueueとは?
MessageQueueはHandler
やLooper
などで使用される機能でアプリケーション内のスレッド間の通信を管理する役割を持っています。MessageQueueはスレッド1つに対して1つ関連づけられており、そのスレッドで処理するタスクを順番に処理していくための構造を持っています。Looper.myQueue()
で現在のスレッドのMessageQueueを取得することができます。
Handler
がMessageQueueにタスクを追加し、Looper
がタスクを取り出し処理を実行していきます。管理されるタスクはメッセージと呼ばれる通信を目的としたタスクとRunnableオブジェクトのような具体的な処理を目的としたタスクの2種類が管理されています。
MessageQueueとは?〜まとめ〜
- キュー構造
- 複数のスレッドでタスクが混ざらないように管理する仕組み
- Handlerがタスクを追加
- Looperがタスクを取り出し処理を実行
- 扱うタスクの種類はメッセージとRunnableオブジェクトなどの具体的なタスク
Runnableオブジェクトとは?
RunnableオブジェクトとはMessageQueueに格納されるタスクの種類の1つです。このオブジェクトが実行すべきコード(処理)を保持しています。保持している場所はrun
メソッド中であり、このメソッドは引数なしかつ返り値のない(Void)のメソッドで定義されています。
Runnableオブジェクト?〜まとめ〜
- タスクの種類の1つ
- 実行すべき具体的なコード(処理)を保持
- Runnableインターフェースとして提供
- 引数なしかつ返り値のない(Void)のrunメソッドのみ定義
Looperとは?
Looperは自身が管理するMessageQueue内のタスクを順番に処理していく役割を持っています。スレッド1つにLooper1つが関連づいているため、マルチスレッド処理を行うためには欠かせない仕組みになります。
例えばUI(メイン)スレッドのLooperを取得したい場合はgetMainLooper
メソッドを使用します。
Looperとは?〜まとめ〜
- スレッド1つに1つのLopperが関連づいている
- MessageQueueを保持している
- タスクを順番に処理していく役割
Handlerのインスタンス化
Handler
をインスタンス化する時は引数に対象のLooperを指定して両者を関連づけます。Looperを渡さずにHandler()
でインスタンス化することも可能ですが、公式から非推奨になっているようで、クラッシュを引き起こす原因になるようです。
遅延処理:postDelayed
postDelayed
メソッドを使用することで処理を任意のミリ秒数遅延させることができます。
ActivityやFragmentで遅延処理を実行し中でViewを操作する時などはviewLifecycleOwner
からCoroutines
で操作するとライフサイクルに依存したスコープになるので安全です。
遅延処理を実装する方法は他にはTimer
などもあります。
カウントアップタイマーを実装してみる
最低限の使い方がわかった上でHandler
やLooper
を使用してカウントアップタイマーを実装してみたいと思います。とりあえず全体のコードは以下のような感じになりました。uiThreadHandler(Handlerオブジェクト)
からいろいろなメソッドを呼び出してタスクを操作しているのがわかると思います。
キューにRunnableオブジェクトを送信
キューにRunnableオブジェクトを送信するにはpost
メソッドを使用します。今回はキューの中にtimerRunnable
オブジェクトが追加され、実行された中でUIを更新する処理をさらにキューへ追加する際に使用しています。
遅延して実行させるタスクをキューへ送信
キューに追加したタスクを遅延実行させるためにはpostDelayed
メソッドを使用します。1つ目の引数に対象のタスクを、2つ目の引数に遅延させたいミリ秒数を指定します。
今回はRunnableオブジェクトの処理の最後で再度自身を1秒後に実行されるようにキューに送信することでループして処理を実行させています。
キュー内のRunnableをすべて削除
キュー内のRunnableをすべて削除させるためにはremoveCallbacks
メソッドを使用します。タイマーが不要になるタイミングやアクティビティが破棄されるタイミングで明示的に削除しておきます。。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。