重い処理をメインスレッドから切り離す

Dispatchers.IO

Jetpack ComposeにおけるDispatchers.IOは、UIをフリーズさせないために、通信やファイル読み書きなどの重い非同期処理をバックグラウンドスレッドで実行するための仕組みです。

Jetpack ComposeのUI描画は常に「Mainスレッド(UIスレッド)」で行われるため、時間のかかる処理をそのまま実行すると画面がカクついたり、アプリが強制終了(ANR)したりします。それを防ぐために Dispatchers.IO へ処理を委託します。

役割と特徴

  • I/O処理に特化:ネットワーク通信(APIコール)、データベース操作(Room等)、ファイルの読み書きに最適化されています。 
  • スレッドの自動管理:処理の「待ち時間」が発生することを想定し、必要に応じて多くのスレッドを柔軟に生成・共有するスレッドプールを持っています。 
  • Mainセーフの実現:重い処理を行う関数内部で withContext(Dispatchers.IO) を使うことで、呼び出し元のMainスレッドをブロックしない「メインセーフ」な関数を作ることができます。 

ディスパッチャーの使い分け

処理の内容に応じて、適切なディスパッチャーを選択する必要があります。

ディスパッチャー主な用途具体例
Dispatchers.MainUI操作、軽量な処理状態(State)の更新、トースト表示
Dispatchers.IOディスク・ネットワーク通信Retrofitによる通信、Roomの読み書き
Dispatchers.DefaultCPU負荷の高い計算処理大規模なリストのソート、画像の加工、JSON解析

Jetpack Composeでの具体的なコード例

Composeの画面内で Dispatchers.IO を利用する場合、コンポジションのライフサイクルに連動する LaunchedEffect などを組み合わせて使用します。

実装時の注意点

  • UI状態の更新タイミングwithContext(Dispatchers.IO) の内部で Compose の MutableState(上記例の userData など)を直接更新することは避けてください。UIの更新は、必ず withContext ブロックが終了した後の Main スレッド上で行うのが安全です。
  • ビジネスロジックの分離:本来、通信やデータ取得の処理は Composable 関数の中に直接書くのではなく、Android公式ドキュメントが推奨するように ViewModel(viewModelScope やリポジトリレイヤに隠蔽し、UI側は単にその状態を観察(Observe)する設計にすることが望ましいです。

普通の関数にsuspendと = withContext(Dispatchers.IO) を付けるだけ

suspend fun save(tableData: List<List<String>>, password: String?) = withContext(Dispatchers.IO) {}
suspend fun load(password: String?): List<List<String>>? = withContext(Dispatchers.IO) {}
タイトルとURLをコピーしました