🧭

LaunchedEffectとは?

2024/02/03に公開

読んでほしい人

  • LaunchedEffectについて知りたい人
  • Jetpack Compose使っている人

補足情報

似たようなライフサイクルを持っている技術を知っている人は理解しやすいと思います。

動画だと、モケラボさんが参考になりそうです。
https://www.youtube.com/watch?v=skUdu6Yqykc

記事の内容

LaunchedEffectは、Jetpack Compose(Androidの新しいUIツールキット)の概念で、特定の条件が変更されたときに副作用(サイドエフェクト)を実行するための関数です。

FlutterのinitStateメソッドとは異なります。initStateは、FlutterのStatefulWidgetが作成されるときに一度だけ呼び出されます。一方、LaunchedEffectは指定したキーが変更されるたびに実行されます。

ReactのuseEffectフックに近いです。useEffectは、指定した依存性リストのいずれかが変更されるたびに実行されます。これはLaunchedEffectの動作と似ています。ただし、LaunchedEffectはJetpack Composeのコルーチンスコープ内で実行され、非同期操作をより簡単に扱うことができます。

タイマーのようなアプリで練習してみました!

package com.example.coroutineexample

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.example.coroutineexample.ui.theme.CoroutineExampleTheme
import kotlinx.coroutines.delay

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            CoroutineExampleTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    Stopwatch()
                }
            }
        }
    }
}

@Composable
fun Stopwatch() {
    var time by remember { mutableStateOf(0L) }
    var start by remember { mutableStateOf(false) }

    // LaunchedEffectは、コンポーズ関数が最初に呼び出されたときに一度だけ実行される
    LaunchedEffect(key1 = start) {
        if (start) {
            while (start) {
                delay(1000L)
                time++
            }
        }
    }

    Column {
        Text(text = "Time: $time")// ここで時間を表示
        Button(onClick = { start = !start }) {// ここでボタンを押したときの処理を実行
            Text(if (start) "Stop" else "Start")// ここでボタンの表示を変更
        }
        // if文でstartがfalseかつtimeが0Lより大きい場合にボタンを表示
        if (!start && time > 0L) {
            Button(onClick = { time = 0L }) {
                Text("Reset")
            }
        }
    }
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    CoroutineExampleTheme {
        Stopwatch()
    }
}

最後に

Flutterのように、ページが呼ばれるたびに1回だけ実行されるわけではなくて、依存しているコード、例えばカウターのロジックが呼ばれるたびに、実行されます。今回だとwhile文でループしてる処理ですね。
まさかタイマーの処理を作るときに、while文使えると知りませんでした!

Discussion