Jetpack Composeは、2021年7月に安定版1.0がリリースされた、GoogleによるAndroid開発向けの最新宣言的UIフレームワークです。Composeは、命令型のXMLレイアウトとViewシステムを、@Composableアノテーション付きのKotlin関数に置き換えます。Google I/O(2025)によると、Composeは新規Androidプロジェクトの55%で使用されており、UIコードの平均サイズはXMLと比較して30~50%削減されています。フレームワークはStateの変更時に、変更された画面部分のみを自動的に再描画し、notifyDataSetChangedやfindViewByIdの手動呼び出しを不要にします。
重要なポイント
Jetpack Composeは、リアクティブプログラミングの原則に基づいて構築されたGoogleのUIフレームワークです。XMLレイアウト、FragmentManager、ViewBindingを使用する代わりに、開発者は@Composableアノテーション付きのKotlin関数を通じてインターフェースを記述します。ComposeはLayoutInflaterを使用しません。UIはバイトコードにコンパイルされる純粋なKotlin関数です。フレームワークは複数のライブラリで構成されています:Compose UI(基本コンポーネントText、Button、Column、Row)、Compose Foundation(Material Design、Gestures、Focus)、Compose Material3(Dynamic Colors対応のMaterial You)、Compose Runtime(State、Side Effects、Coroutines)。ComposeはAndroid API 21+(Android 5.0)で動作し、ComposeView(AndroidViewアダプター)を介して既存のView/XMLコードと完全に互換性があります。
View System(2008年)は、手動管理によるViewオブジェクトの階層を使用します。開発者はXMLレイアウトを作成し、findViewByIdでViewを見つけ、RecyclerView用のAdapterを実装し、データ変更時にnotifyDataSetChangedを呼び出します。ComposeはUIを関数的に記述します。状態が変更されると、フレームワークは変更されたComposable関数のみを再コンポーズし、差分を計算してCanvasに最小限の変更を適用します。ComposeのパフォーマンスはView Systemと同等で、複雑なリスト(LazyColumn)を使用するシナリオでは、keyパラメータによって不要な要素をスキップするため、RecyclerViewを上回ることがよくあります。IT Sectrでは、ComposeはminSdk 24+のAndroidアプリケーションの新しいモジュールに使用されています。
@Composable — 通常のKotlin関数をUIの構成要素に変換するアノテーションです。Composable関数は他のComposable関数を呼び出して、コンポーネントツリーを形成できます。Viewとは異なり、Composable関数はデフォルトで状態を持ちません。ステートレスであり、入力パラメータまたはStateが変更されるたびに再描画されます。Compose Compilerは@Composable関数を、中断および再開可能なコード(positional memoization)に変換します。これにより、Composeはツリーを完全に再構築することなく、変更された部分のみを再実行できます。
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
fun UserProfile(name: String, avatarUrl: String) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
AsyncImage(
model = avatarUrl,
contentDescription = "User avatar",
modifier = Modifier.size(48.dp)
)
Spacer(modifier = Modifier.width(12.dp))
Text(
text = name,
style = MaterialTheme.typography.titleMedium
)
}
}UserProfile関数はnameとavatarUrlをパラメータとして受け取り、アバターと名前を含む行を構築します。Modifier.fillMaxWidth()はコンポーネントを全幅に引き伸ばし、.padding(16.dp)はパディングを追加します。MaterialTheme.typography.titleMediumはシステムのMaterial 3スタイルを使用します。nameまたはavatarUrlパラメータが変更されると、ComposeはUserProfileを再コンポーズし、新しい値でコンポーネントを再作成します。
StateはComposeにおいて、その変更が依存する@Composable関数の再コンポーズ(再実行)をトリガーする任意の値です。基本的な方法はmutableStateOf()で、ComposeのスナップショットシステムをサポートするMutableState<T>を作成します。スナップショットは変更追跡メカニズムです。Stateに書き込むと、Composeは現在のスナップショットをダーティとしてマークし、再コンポーズスケジューラはそのStateを読み取っているComposable関数のみを再実行します。監視可能なコレクションにはmutableStateListOf()とmutableStateMapOf()を使用します。Composeは、Kotlin Flow用のcollectAsState()とLiveData用のobserveAsState()を介して、Lifecycle-AwareコンポーネントからのStateをサポートしています。
@Composable
fun LikeButton() {
var liked by remember { mutableStateOf(false) }
var count by remember { mutableStateOf(42) }
Button(
onClick = {
liked = !liked
if (liked) count++ else count--
},
colors = ButtonDefaults.buttonColors(
containerColor = if (liked) MaterialTheme.colorScheme.primary
else MaterialTheme.colorScheme.surfaceVariant
)
) {
Text("♥ $count")
}
}このコードは、mutableStateOf()を介して保存されたliked(Boolean)とcount(Int)の状態を持つ「いいね」ボタンを作成します。押すとlikedが反転し、カウンターが増減します。Composeは自動的にLikeButtonを再コンポーズします。byデリゲートを使用すると、liked.value = !liked.valueの代わりにliked = !likedのように、Stateを通常の変数のように使用できます。ボタンの色は、primary(いいね済み)とsurfaceVariant(いいね未済)の間でリアクティブに変化します。
remember — 再コンポーズ間で値をキャッシュするCompose関数です。rememberがないと、Composable関数が再実行されるたびに新しい状態(mutableStateOf)が作成されます。これによりアプリケーションのロジックが破壊されます。画面回転や親Stateの変更時にカウンターがリセットされます。rememberは計算ラムダを受け取り、最初のコンポジションでのみ値を計算し、後続のコンポジションではキャッシュされた結果を返します。キャッシュをリセットするにはremember(key)を使用します。キーは値を再計算するタイミングを決定します。remember(key1, key2)はいずれかのキーが変更されると再計算します。長期間存続する状態(画面回転に耐える)にはrememberSaveableを使用します。これはSavedStateHandleを介してBundleに保存するrememberの類似機能です。
@Composable
fun TimerScreen() {
var seconds by rememberSaveable { mutableStateOf(0) }
LaunchedEffect(Unit) {
while (true) {
delay(1000)
seconds++
}
}
Column(
modifier = Modifier.fillMaxSize().padding(32.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Elapsed: ${seconds}s",
style = MaterialTheme.typography.displayMedium
)
}
}rememberSaveableは画面回転(構成変更)時にsecondsを保持します。LaunchedEffectは毎秒secondsをインクリメントするコルーチンを起動します。TimerScreenの再コンポーズ(毎秒)時、rememberSaveableのおかげでsecondsはリセットされません。構成変更を耐えるべきでない状態(アニメーションフラグなど)には通常のrememberを使用します。
Modifier — Composableコンポーネントの外観、動作、レイアウトを構成するためのBuilderパターンを実装した不変のコンテナオブジェクトです。Modifierメソッド(.padding()、.width()、.clickable()、.background())の呼び出しごとに、要素が追加された新しいModifierが返されます。Modifierの順序は重要です。.padding(16.dp).clickable { } — パディングがクリックハンドラの前に適用され、clickableはパディングを含む領域全体を追跡します。.clickable { }.padding(16.dp) — パディング前の領域全体がクリック可能で、パディングがコンテンツを内側に移動させます。Modifierはthen(otherModifier)によるカスタム実装と、親設定にアクセスするためのcompositionLocalをサポートしています。
@Composable
fun CardExample() {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
.clickable { println("Card clicked") },
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant
)
) {
Column(modifier = Modifier.padding(16.dp)) {
Text("Jetpack Compose", style = MaterialTheme.typography.titleLarge)
Spacer(modifier = Modifier.height(8.dp))
Text(
"StateとModifierを使用したAndroid向け宣言的UI",
style = MaterialTheme.typography.bodyMedium
)
}
}
}CardExampleはModifierチェーン(fillMaxWidth + padding + clickable)を示しています。Cardは独自のelevationとcolors設定を持つMaterial3コンポーネントです。ネストされたColumnは内部パディングが16dpです。Compose Material3はAndroid 12+でDynamic Color(Material You)に自動的に色を適応させます。CardはComposeに組み込まれている30以上のMaterial3コンポーネントの1つです。
State hoisting — 状態をComposable関数からその呼び出し元に引き上げるパターンで、関数をステートレスにします。ステートレスコンポーネントは、State自体を所有せずに、パラメータを介してデータとコールバックを受け取ります。これにより再利用性とテスト容易性が向上します。コンポーネントを異なるStateで呼び出してプレビューでテストできます。Googleが推奨するアーキテクチャはViewModel + StateFlow(またはMutableStateFlow)+ ComposeでのcollectAsState()です。ViewModelが状態を画面レベルに引き上げ、Composeがレンダリングします。副作用(LaunchedEffect、DisposableEffect)は1回限りのイベントを処理します。
| コンポーネント | 責任 | テクノロジー |
|---|---|---|
| ViewModel | Stateの保存、ビジネスロジック | StateFlow、MutableStateFlow |
| Screen Composable | 画面構成、State hoisting | collectAsState()、Scaffold、LazyColumn |
| Stateless Component | 状態のないUI、純粋なレンダリング | @Composableパラメータ+ラムダ |
| Side Effect | 1回限りのアクション(スナックバー、ナビゲーション) | LaunchedEffect、SnackbarHostState |
よくある質問
XMLレイアウトは命令型です。LayoutInflaterがXMLをロードし、findViewByIdがViewを見つけ、開発者が手動でテキストやリストを更新します。Composeは宣言型です。UIはKotlinの@Composable関数で記述され、フレームワークはStateの変更時に変更された部分のみを自動的に再描画します。ComposeはUIコード量を30~50%削減し、XMLを使用しません。
はい、GoogleはNavigation Composeを提供しています。これは画面間の宣言的ナビゲーションのためのライブラリです。NavControllerがルートスタックを管理し、composable()が画面を登録し、navArgumentがパラメータを渡します。代替手段としてはVoyager(コミュニティ)とDecompose(Badoo)があります。Navigation Composeはディープリンクと型安全な引数をサポートする公式標準です。
Modifierは、Composableコンポーネントに適用される装飾パターン(padding、size、clickable、background、border、clip)の不変コンテナです。呼び出しごとに要素が追加された新しいModifierが返されます。順序が重要です。.padding().clickable()はクリック前にパディングを適用し、.clickable().padding()はその逆です。ModifierはComposeコンポーネントをカスタマイズする主要な方法です。
Jetpack ComposeはCompose CompilerとCompose BOMを介してAndroid API 21+(Android 5.0 Lollipop)をサポートしています。Material 3(Dynamic Colors)はAndroid 12+で利用可能です。古いバージョンではフォールバックパレットが使用されます。新しいプロジェクトでは、GoogleはminSdk 24+(Android 7.0)を推奨しており、Composeで完全にカバーされています。
GoogleはCompose UI Testを提供しています。これはJVM(デスクトップ)およびエミュレータでのテスト用ライブラリです。主な関数:composeTestRule.setContent { }でコンポーネントをレンダリング、onNodeWithText()で要素を検索、performClick()/performTextInput()でアクションを実行します。EspressoテストはComposeTestRuleを介してComposeと互換性がありますが、Compose UI Testが推奨されるより高速なアプローチです。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。