はじめに
かつてのAndroid開発では、UIをXMLで記述し、KotlinやJavaのコードからそれを操作する「命令的な」アプローチが主流でした。しかし、この方法ではUIが複雑になるにつれてコードが煩雑になり、状態管理のミスも起こりがちでした。
現在、Android開発の世界は大きな変革を遂げました。Googleが公式に推奨する「モダンAndroid開発」は、プログラミング言語としてKotlinを、そしてUIツールキットとしてJetpack Composeを全面的に採用しています。この組み合わせにより、より少ないコードで、より直感的かつ堅牢なアプリケーションを構築できるようになりました。
この記事では、これからAndroid開発を始める方や、従来の手法から移行したいと考えている開発者に向けて、KotlinとJetpack Composeを使ったモダンなアプリ開発の基本を、シンプルなToDoアプリを作りながらステップバイステップで解説します。
最短で課題解決する一冊
この記事の内容と高い親和性が確認できたベストマッチです。早めにチェックしておきましょう。
Jetpack Composeとは?
Jetpack Composeは、AndroidのUIを宣言的に記述するためのモダンなツールキットです。これは、ReactやFlutter、SwiftUIなどと同じ考え方に基づいています。
- 命令的UI(従来): 「ボタンがクリックされたら、テキストビューの文言を『Hoge』に変更しろ」と、UIの変更手順を一つ一つコードで記述する。
- 宣言的UI(Compose): 「テキストビューの文言は、この『状態』の値である」と定義するだけ。あとは『状態』が変われば、UIが自動的に再描画される。
この「状態(State)が変われば、UIが自動的に更新される」というシンプルなコンセプトにより、UIのコードが劇的にシンプルになり、バグの発生も抑えられます。
さらに理解を深める参考書
関連記事と相性の良い実践ガイドです。手元に置いて反復しながら進めてみてください。
プロジェクトのセットアップ
- 最新版のAndroid Studioを起動し、
[New Project]を選択します。 Phone and Tabletタブから、[Empty Activity](Composeロゴが付いているもの)を選択し、[Next]をクリックします。- アプリケーション名(例:
MyToDoApp)、パッケージ名、保存場所を設定します。言語がKotlinになっていることを確認し、[Finish]をクリックします。
これだけで、Jetpack Composeを使うための基本的な設定(build.gradle.ktsへの依存関係の追加など)が完了したプロジェクトが作成されます。
さらに理解を深める参考書
関連記事と相性の良い実践ガイドです。手元に置いて反復しながら進めてみてください。
シンプルなToDoアプリの構築
それでは、タスクの追加、完了、削除ができる簡単なToDoアプリを作っていきましょう。
Step 1: データクラスの定義
まず、一つのToDoタスクを表すデータクラスを作成します。com.example.mytodoapp(あなたのパッケージ名)の直下に、TodoItem.ktという新しいKotlinファイルを作成します。
data class TodoItem(
val id: Int,
val text: String,
var isDone: Boolean = false
)Step 2: ViewModelの導入
UIの状態(ToDoリストなど)と、それを操作するロジックをUIから分離するためにViewModelを使用します。これは、画面回転などでUIが再生成されても状態を安全に保持するための、モダンAndroid開発における標準的なアーキテクチャです。
build.gradle.kts(appモジュール)のdependenciesブロックに、ViewModelをComposeで使うためのライブラリを追加します。
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.0") // 2025年9月時点の例次に、TodoViewModel.ktという新しいファイルを作成します。
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
class TodoViewModel : ViewModel() {
// UIに公開するToDoリストの状態
// asStateFlow()で読み取り専用にするのがポイント
private val _todoItems = MutableStateFlow<List<TodoItem>>(emptyList())
val todoItems = _todoItems.asStateFlow()
private var nextId = 1
fun addTodo(text: String) {
val newItem = TodoItem(id = nextId++, text = text)
_todoItems.value = _todoItems.value + newItem
}
fun toggleDone(id: Int) {
_todoItems.value = _todoItems.value.map {
if (it.id == id) it.copy(isDone = !it.isDone) else it
}
}
}Step 3: UIコンポーザブルの作成
Jetpack Composeでは、UIの部品を@Composableアノテーションを付けた関数(コンポーザブル)として定義します。
MainActivity.ktを開き、既存のコードを以下のように全面的に書き換えていきましょう。
package com.example.mytodoapp
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.mytodoapp.ui.theme.MyToDoAppTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyToDoAppTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
TodoScreen()
}
}
}
}
}
@Composable
fun TodoScreen(todoViewModel: TodoViewModel = viewModel()) {
// ViewModelのStateFlowを監視し、変更があればUIを再描画
val todoItems by todoViewModel.todoItems.collectAsState()
var inputText by remember { mutableStateOf("") }
Column(modifier = Modifier.padding(16.dp)) {
// 入力欄と追加ボタン
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
OutlinedTextField(
value = inputText,
onValueChange = { inputText = it },
label = { Text("新しいタスク") },
modifier = Modifier.weight(1f)
)
Spacer(modifier = Modifier.width(8.dp))
Button(onClick = {
if (inputText.isNotBlank()) {
todoViewModel.addTodo(inputText)
inputText = "" // 入力欄をクリア
}
}) {
Text("追加")
}
}
Spacer(modifier = Modifier.height(16.dp))
// ToDoリスト
LazyColumn(modifier = Modifier.fillMaxSize()) {
items(todoItems, key = { it.id }) { item ->
TodoItemRow(item = item, onToggle = { todoViewModel.toggleDone(item.id) })
}
}
}
}
@Composable
fun TodoItemRow(item: TodoItem, onToggle: () -> Unit) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Checkbox(checked = item.isDone, onCheckedChange = { onToggle() })
Spacer(modifier = Modifier.width(8.dp))
Text(
text = item.text,
textDecoration = if (item.isDone) TextDecoration.LineThrough else null
)
}
}コードのポイント:
@Composable: UIを定義する関数の目印です。viewModel(): ViewModelのインスタンスを取得します。collectAsState(): ViewModelが持つStateFlowを監視し、その値が変更されるたびにUIの再描画(Recomposition)をトリガーします。remember { mutableStateOf(...) }: コンポーザブル内の状態(ここではテキスト入力欄の文字列)を記憶するための仕組みです。LazyColumn: 表示領域に必要なアイテムだけを描画する、効率的なリスト表示用のコンポーザブルです。
Step 4: アプリの実行
これで全て完了です。Android Studioの実行ボタン(▶️)を押して、エミュレータや実機でアプリを起動してみましょう。タスクの追加や、チェックボックスでの完了状態の切り替えができるはずです。
さらに理解を深める参考書
関連記事と相性の良い実践ガイドです。手元に置いて反復しながら進めてみてください。
まとめ
今回は、モダンAndroid開発の中核であるKotlinとJetpack Composeを使い、シンプルなToDoアプリを構築しました。状態(State)を定義し、それに基づいてUIを宣言的に記述することで、従来のXMLと命令的なコードの組み合わせよりも、はるかに見通しが良く、メンテナンスしやすいコードになることを感じていただけたのではないでしょうか。
ここからさらに、Roomデータベースを使ったデータの永続化や、マテリアルデザインのカスタマイズ、画面遷移(ナビゲーション)など、より高度な機能を実装していくことになります。
ぜひ公式ドキュメントなどを参考に、モダンAndroid開発の世界をさらに探求してみてください。
さらに理解を深める参考書
関連記事と相性の良い実践ガイドです。手元に置いて反復しながら進めてみてください。

![Amazon Bedrock 生成AIアプリ開発入門 [AWS深掘りガイド]](https://m.media-amazon.com/images/I/51KtyIMPsYL._SL500_.jpg)

