【Androidアプリ開発】Kotilinの最新版であるJetpack Composeについて詳しく解説します

【Androidアプリ開発】Kotilinの最新版であるJetpack Composeについて詳しく解説します

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で自動反映

関連記事

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

フリーランスエンジニアとして活動。
主に業務システムの要件定義~保守まで幅広く担当しています。
お気軽にお問い合わせください。

【趣味】
筋トレ/読書/プログラミング/資格の勉強

コメント

コメントする

目次