Kotlin非同期関数

基本

非同期関数作成には fun の前に【suspend】を付ける

// 非同期関数(suspendを付ける)
suspend fun fetchRemoteData(): String {
    delay(2000) // 2秒待機する模擬処理
    return "サーバーから取得したデータ"
}

呼び出しには【LaunchedEffect】を使用すして【suspend】関数を囲む

ただこれだと再描写のたびに呼ばれたりするので以下を参照

条件発火

Jetpack Composeで非同期関数(suspend 関数)を呼び出すには、Google公式が推奨する副作用(Side-Effect)APIの LaunchedEffect または rememberCoroutineScope を使用します

Composeの関数内で直接非同期関数を呼び出すと、画面が更新(再コンポーズ)されるたびに何度も実行されてしまい、アプリの動作が不安定になるため注意が必要です。

主要な2つの使い方

用途に合わせて以下の2つを使い分けます。

実現したいこと使うAPI主な用途
画面が開いた時に自動実行LaunchedEffectAPIからのデータ取得、初期化処理
ボタンを押した時に実行rememberCoroutineScope保存ボタンのタップ、ユーザー操作起点

1. 画面表示時に自動で動かす (LaunchedEffect)

画面の表示開始時や、特定のデータが変化したタイミングで非同期処理を行いたい場合に使用します。 [6] 

@Composable
fun MyScreen() {
    var text by remember { mutableStateOf("読み込み中...") }

    // Unitをキーに指定すると、この画面が最初に表示された時だけ1回実行される
    LaunchedEffect(Unit) {
        text = fetchRemoteData() // 非同期関数の呼び出し
    }

    Text(text = text)
}

// 疑似的な非同期関数
suspend fun fetchRemoteData(): String {
    delay(2000) // 2秒待機
    return "データ取得完了!"
}

2. ボタン操作などのイベントで動かす (rememberCoroutineScope)

ボタンの onClick など、Composabilityの外部(コールバック関数内)からコルーチンを起動したい場合に使用します。

@Composable
fun MyButtonScreen() {
    // コルーチンスコープを取得
    val scope = rememberCoroutineScope()
    var status by remember { mutableStateOf("未実行") }

    Button(onClick = {
        // ボタンを押した時にスコープから起動する
        scope.launch {
            status = "処理中..."
            saveDataToServer() // 非同期関数の呼び出し
            status = "保存完了!"
        }
    }) {
        Text("サーバーに保存 ($status)")
    }
}

suspend fun saveDataToServer() {
    delay(1500)
}

💡 ベストプラクティス:ViewModelの活用

本格的なアプリ開発では、UI層(Compose)で直接非同期処理を管理するのではなく、ViewModel 内の viewModelScope で非同期関数を実行する のが最も安全で一般的な設計です。

class MyViewModel : ViewModel() {
    var uiState by mutableStateOf("初期状態")
        private set

    fun loadData() {
        // 画面の回転や破棄が起きても安全に非同期処理が継続・キャンセルされる
        viewModelScope.launch {
            uiState = fetchRemoteData()
        }
    }
}

コメント

タイトルとURLをコピーしました