UIはもっとシンプルに書ける。状態管理はViewModelに任せよう!
ということで、今回はJetpack ComposeというAndroidStudioの新たなフレームワークを解説します。
従来はxmlでUIを作成していましたが、なんとJetpack ComposeではUIをkotlinで作成できます。
なんだかSwiftUIに似てきましたね。
では、実際に概要と詳細を解説します。
- Jetpack Composeについて知りたい
- UIをより簡素に書きたい
- これからKotilinでAndroidアプリを作成したい
Jetpack Composeで必要なViewModel
Jetpack Compose を触り始めると、まずぶつかるのが「状態管理どうする問題」。
画面を横に向けたりすると、保持していたデータが初期化されてしまうという欠点があります。
remember や mutableStateOf だけで頑張っていると、画面回転で値が消えたり、複雑な画面で破綻したりします。
そこで登場するのが ViewModel。
Compose と組み合わせると、UIが驚くほどスッキリします。
ViewModelが必要な理由
Compose は「状態が変わると UI を再描画する」仕組み。
つまり、状態(State)をどこに置くかが超重要です。
- 画面回転しても消えない
- UIロジックとデータロジックを分離できる
- Room や Repository と自然につながる
これらを全部満たすのが ViewModelです!
Jetpack Compose×ViewModelの実装方法
Step 1:ViewModel を作る
まずは最小構成の ViewModel。
class MainViewModel : ViewModel() {
private val _count = MutableStateFlow(0)
val count = _count.asStateFlow()
fun increment() {
_count.value += 1
}
}- MutableStateFlow は Compose と相性抜群
- asStateFlow() で外部から書き換え不可に
- viewModelScope.launch {} で非同期処理も安全
Step 2:Compose で ViewModel を使う
build.gradleファイルに下記を追加する。
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.10.0")「2.10.0」の部分については「https://developer.android.com/jetpack/androidx/releases/lifecycle?hl=ja」に表示される最新版を指定してください。
このコードに黄色い波線ができるので、右クリック→💡→synnowを押下するとインストールが始まります。
Compose 側でimportしてviewModel() を呼ぶだけ。
import androidx.lifecycle.viewmodel.compose.viewModel@Composable
fun CounterScreen(viewModel: MainViewModel = viewModel()) {
val count by viewModel.count.collectAsState()
Column {
Text("Count: $count")
Button(onClick = { viewModel.increment() }) {
Text("Add")
}
}
}- viewModel() は自動で ViewModel を提供
- collectAsState() で Flow を UI に反映
- UIが再描画されても ViewModel は破棄されない
Step 3:Room / Repository とつなげる
実務では ViewModel が DB を直接触らず、Repository を経由します。
class ExpenseViewModel(
private val repository: ExpenseRepository
) : ViewModel() {
val expenses = repository.getAllExpenses()
fun addExpense(expense: Expense) {
viewModelScope.launch {
repository.insert(expense)
}
}
}Compose 側:
@Composable
fun ExpenseListScreen(viewModel: ExpenseViewModel = viewModel()) {
val expenses by viewModel.expenses.collectAsState(initial = emptyList())
LazyColumn {
items(expenses) { e ->
Text("${e.date} : ${e.amount}円")
}
}
}Step 4:ViewModel に引数がある場合(Factory or Hilt)
Repository を渡す必要がある場合は Factory を使います。
class ExpenseViewModelFactory(
private val repository: ExpenseRepository
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return ExpenseViewModel(repository) as T
}
}Compose 側:
val viewModel: ExpenseViewModel = viewModel(
factory = ExpenseViewModelFactory(repository)
)まとめ
以上で実装方法や概要を解説しました。
Compose × ViewModel は現代Androidの“正解”と言えるでしょう!
現代ではよりシンプルにUIをコードで書くことが求められます。
ViewModelを活用しながらスマートな可読性の高いプログラムを組みましょう。
- UIはCompose
- 状態管理はViewModel
- データはRoom
- データ取得はRepository
- UI更新はFlowで自動反映
関連記事



コメント