Jetpack ComposeのonClickでコルーチンを使いたい
Jetpack ComposeのButtonのonClickなど、イベントのコールバック関数内で時間のかかる処理をしたい場合は、rememberCoroutineScope()を使います。起動したコルーチンを停止する方法も説明します。
やりたいこと

例として、一定時間内にボタンが3回タップされたかどうかを判定する、トリプルタップボタンを作成します。ボタンタップ時の処理はButtonのonClickコールバックに処理を書くので、このコールバック関数内でコルーチン (Coroutnie) を呼び出す必要があります。また、条件によってコルーチンをキャンセルする必要もあります。
環境
- Kotlin 1.6.10
- Jetpack Compose 1.1.1
- Material3 1.0.0-alpha12
ソースコードと説明
TripleTapButton()は、Button()をラップし、トリプルタップが成立したらonTripleTap()をコールバックする関数です。
@Composablefun TripleTapButton(onTripleTap: ()->Unit, content: @Composable RowScope.()->Unit) { val scope = rememberCoroutineScope() var job: Job? = remember{ null } var tapCount = remember { 0 } Button( onClick = { if (tapCount == 0) { job = scope.launch { delay(1000) tapCount = 0 } } tapCount++ if (tapCount >= 3) { job?.cancel() onTripleTap() tapCount = 0 } }, content = content )}rememberCoroutineScope
コルーチンを起動するためのスコープは、rememberCoroutineScope()で取得します。rememberCoroutineScope()で取得したCoroutineScopeは、最初のコンポジションで作成され、再コンポジションが走っても保持されます。そして、コンポジションから退出するタイミングで、実行中のコルーチンをキャンセルして削除されます。
注意すべきポイントは、rememberCoroutineScope()で作成したCoroutineScopeを使えるのは、コンポーザブルではなく普通のUIスレッドだということです。つまり、onClickなどのコールバック関数内でコルーチンを使いたいときに、rememberCoroutineScope()を使います。
ちなみに、コンポーザブルでコルーチンを使いたい場合は、LaunchedEffectを使います。
コルーチンを起動する
トリプルタップの判定のために、最初のタップから一定時間以内のタップ数をカウントします。そこで、最初のタップ発生時に、rememberCoroutineScope()で取得したCoroutineScopeに対してlaunch()を呼び出して、コルーチンを起動します。launch()の戻り値はJobです。これはあとでキャンセルするときのために、remember変数で保持しておきます。
コルーチン内では、delay()を使い、一定時間後にタップ数をゼロに戻すという処理をしています。これが実行されたときは、トリプルタップが成立しなかったということになります。
コルーチンをキャンセルする
onClickは、呼ばれるたびにタップ数をインクリメントします。コルーチン内の処理によってタップ数がゼロにリセットされるより早く、タップ数が3に到達すれば、トリプルタップ成立です。トリプルタップが成立したら、起動中のコルーチンをキャンセルしなければなりません。コルーチンのキャンセルは、launch()の戻り値として取得したJobに対してcancel()を呼び出すことで可能です。
トリプルタップが成立したら、コルーチンをキャンセルし、TripleTapButton()のコールバック関数を呼び出し、タップ数をゼロにリセットしています。
まとめ
Jetpack Composeでコルーチンを使う方法はいくつかのバリエーションがあって、最初は難しく感じるのですが、もっともシンプルな使い方としては、コンポーザブル内で使う場合はLaunchedEffect()、コールバック関数内で使う場合はrememberCoroutineScope()と考えておけばよいです。
余談ですが、Androidのボタンなどのコンポーネントを「タップ」した時のイベントがon”Click”と呼ぶことにいつも違和感を感じます。英語ではあまり”tap”と言わないのでしょうか。
