Jetpack Composeは、KotlinでAndroidインターフェースを構築するためのモダンな宣言型ツールキットです。開発者はcomposable関数を通じてUIを記述し、ツールキットは変更された部分のみを自動的に再描画します。Android Developers (2026)によると、Jetpack ComposeはAndroid 5.0(API 21)以上で動作し、Material Design 3をサポートし、ミッドレンジデバイスで120 FPSを達成します。これは独自のRecompositionシステム(変更されたウィジェットのみを更新するスマートなdiffアルゴリズム)によるものです。
主要ポイント
Jetpack Composeは、Googleが2019年に発表し2021年に安定版リリースを迎えた、Androidユーザーインターフェース構築のための宣言型フレームワークです。古いView System(XMLレイアウト+Activity/Fragment)とは異なり、Composeはアノテーション付きのKotlin関数(@Composable)を使用します。インターフェースはすべてKotlinで記述され、XMLとコードの分離はありません。これにより、XMLとKotlinのID不一致に関連するエラーが排除されました(type-safe syntheticはリファクタリング時に役立ちませんでした)。
Composeは独自のレンダリングシステムCanvas上に構築されており、View階層に依存しません。各ComposableはView SystemのonMeasure/onDrawをバイパスして、Canvasに直接描画します。これにより複雑な画面でのパフォーマンスが向上します:Googleのテスト(2023年)では、200要素のCompose画面はRecyclerView+ViewHolderの同様の画面より40%高速にレンダリングされました。
ComposeにはminSdk 21(Android 5.0)とKotlin 1.9+が必要です。Compose BOM(Bill of Materials)がすべてのComposeライブラリのバージョンを同期します。このフレームワークは既存のView Systemコードと互換性があります:ComposeはComposeViewを介してXMLレイアウトに埋め込まれ、古いViewはAndroidViewを介してCompose階層に埋め込まれます。Google Play Console(2025年)によると、Android 5.0+はアクティブデバイスの97%をカバーしており、ほとんどのプロジェクトで互換性は制限になりません。
@Composableは、通常のKotlin関数をUI構成要素に変換するアノテーションです。Composable関数は、インターフェースの一部(テキスト、ボタン、リスト)がどのように見えるかを記述します。値を返す代わりに、関数はコンポジションにUIコンポーネントを出力(emit)します。これはジェネレーターに似ており、各関数は呼び出されると画面に要素を追加します。
@Composable
fun ProfileCard(name: String, avatarUrl: String) {
Card(
modifier = Modifier.fillMaxWidth().padding(16.dp),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surface
)
) {
Row(verticalAlignment = Alignment.CenterVertically) {
AsyncImage(
model = avatarUrl,
contentDescription = "アバター",
modifier = Modifier.size(48.dp).clip(CircleShape)
)
Spacer(Modifier.width(12.dp))
Text(
text = name,
style = MaterialTheme.typography.titleMedium
)
}
}
}
ProfileCard関数はパラメータ(name、avatarUrl)を受け取り、Card → Row → AsyncImage + Textを出力します。コンポジションは、1回のパスで出力されたコンポーネントのツリーです。パラメータが変更されていない場合、Composeは関数呼び出しをスキップします(recomposition skip)。nameのみが変更された場合、Textのみが呼び出され、残りの要素は再描画されません。このインテリジェントな再コンポジションは、手動のView System最適化に対するComposeの主要なパフォーマンス上の利点です。
Composable関数はスロット(trailing lambda、content: @Composable (() -> Unit))を積極的に使用します。これにより、Card、Column、Rowなどのコンテナを作成でき、コンテンツはスロットに埋め込まれます。Slot APIはandroid:layout_gravityのようなXML属性を置き換えました。子要素の配置はコンテンツブロック内のKotlinコードで設定されるようになりました。
Composeにおける状態(State)とは、時間とともに変化する可能性のある値のことです。状態が変わると、Composeはその状態を読み取っているすべてのコンポーネントの再コンポジションをスケジュールします。この仕組みはReact hooksに似ています:mutableStateOfはMutableState<T>を返し、.valueを読み取ると、現在のコンポジションが自動的に変更を購読します。
@Composable
fun CounterExample() {
var count by remember { mutableStateOf(0) }
Column(modifier = Modifier.padding(16.dp)) {
Text("クリックされました: $count")
Button(onClick = { count++ }) {
Text("増やす")
}
}
}
@Composable
fun UserScreen(viewModel: UserViewModel) {
val userName by viewModel.userName.collectAsState()
Text("ユーザー: $userName")
}
rememberは再コンポジション間で値を保持します。そうでなければ、UIが更新されるたびにmutableStateOfが新しく作成されます。collectAsState()はViewModelのStateFlowをCompose互換の状態に変換します。推奨事項 — 画面レベルの状態にはViewModelとStateFlowを、ローカル状態(展開されたカードなど)にはmutableStateOfを使用します。この分離はスマート/ダムコンポーネントの原則に従います。
State Hoistingは、子コンポーネントから親コンポーネントに状態を引き上げるパターンです。親はパラメータを介して値とコールバックを渡し、子は変更時にコールバックを呼び出します。親がmutableStateOfを保持し、子はパラメータのみを保持します。これによりコンポーネントが再利用可能かつテスト可能になります。同じTextFieldを任意のデータソースで使用できます。
Modifierは、Composableの変換(サイズ、パディング、背景、クリック処理、アニメーション、スクロール)を記述するオブジェクトです。モディファイアは呼び出しチェーンで適用されます:Modifier.fillMaxWidth().padding(16.dp).background(Color.Blue).clickable { }。各呼び出しはプロパティが追加された新しいModifierを返します。元のオブジェクトは変更されません。
モディファイアの順序は重要です。Modifier.padding(16.dp).background(Color.Blue)はパディング付きの領域を塗りつぶします。Modifier.background(Color.Blue).padding(16.dp)は内側の長方形を塗りつぶし、パディングは透明のままです。仕組みはCSSボックスモデルに似ています:paddingを先に→backgroundはmargin+backgroundのように機能。backgroundを先に→paddingはbackground+内部パディングのように機能。開発者は次のことを覚えておけば十分です:paddingを先に=外部マージン、paddingを後に=内部パディング。
組み込みのモディファイアで不十分な場合、Modifier.composed { ... }またはModifier.then()でカスタムモディファイアを作成します。カスタムモディファイア内では、レイアウト測定(Modifier.layout { measurable, constraints -> ... })、描画(Modifier.drawWithContent { ... })、ジェスチャー(Modifier.pointerInput { ... })を使用できます。例:クリック時のパルスアニメーション用モディファイア — サイズを測定し、クリック時にanimateFloatAsStateでスケールアニメーションを開始します。
アニメーション用に、Composeはanimate*AsState(animateFloatAsState、animateColorAsState、animateDpAsState)を提供します。変更時に値が古い状態と新しい状態の間でアニメーションします。出入りアニメーションにはAnimatedVisibilityとAnimatedContentに組み込みのトランジション(フェード、スライド、展開)があります。すべてのアニメーションはグラフィックスレイヤーで動作し、不要なコンポジションをトリガーしません。
Composable関数は直接副作用(ネットワークリクエスト、タイマー、サブスクリプション)を実行すべきではありません。毎回の再コンポジションで呼び出されるため、リクエストが重複します。副作用のために、ComposeはEffect関数ファミリーを提供します:LaunchedEffectはコンポジションへの入場時にコルーチンを開始し、退場時にキャンセルします。DisposableEffectは明示的なクリーンアップが必要なリソース(センサー、BroadcastReceiver)用です。
@Composable
fun SensorReader() {
val context = LocalContext.current
var sensorValue by remember { mutableStateOf(0f) }
DisposableEffect(Unit) {
val sensor = registerSensorListener(context) { value ->
sensorValue = value
}
onDispose {
unregisterSensorListener(sensor)
}
}
Text("値: $sensorValue")
}
@Composable
fun UserGreeting(userId: String) {
LaunchedEffect(userId) {
val profile = api.fetchProfile(userId)
// 状態更新
}
}
LaunchedEffect(userId)はuserIdが変わると再起動します。前のコルーチンはキャンセルされ、新しいuserIdで新しいコルーチンが開始されます。これにより手動のリクエストキャンセル管理が不要になります。DisposableEffect(Unit) — 固定キーUnitを持つエフェクトで、コンポジション入場時に発火し、退場時にonDisposeを呼び出します。SensorReaderはリスナーを登録し、画面離脱時に購読を解除 — リークのリスクなし。
コンポジション入場時ではなく、イベント(ボタンクリック)でコルーチンを起動する必要がある場合は、rememberCoroutineScope()を使用します。Composableのライフサイクルに紐づいたCoroutineScopeを返し、DisposableEffectは不要です。例:ボタンクリックでネットワークリクエストを開始 — scope.launch { viewModel.loadData() }。
ComposeとView Systemの選択は、2026年のAndroid開発者にとって主要なアーキテクチャ上の問題です。両方のテクノロジーはGoogleによってサポートされていますが、ComposeがGoogleがリソースを投じる主要な方向性です。View Systemは重要な修正のみを受け取り、進化していません。違いは構文、状態管理、パフォーマンス、開発時間に現れます。
| 側面 | Jetpack Compose | View System |
|---|---|---|
| UIの記述 | Kotlin @Composable関数 | XMLレイアウト+Activity/Fragment |
| 状態 | mutableStateOf、StateFlow、自動再描画 | findViewById、手動:setText、notifyDataSetChanged |
| パフォーマンス | インテリジェントな再コンポジション、Canvasレンダリング | View階層、measure/layout/draw |
| アニメーション | animate*AsState、AnimatedVisibility、組み込み | ValueAnimator、ObjectAnimator、Transition |
| 互換性 | minSdk 21、ComposeView/AndroidViewブリッジ | すべてのバージョン、任意 |
| APKサイズ | Composeで+3–5 MB | オーバーヘッドなし |
新しいプロジェクトでは、GoogleはJetpack ComposeをUI開発の標準として推奨しています。View Systemは2021年以前に書かれたコードの保守と、APKサイズを最小限に抑える必要がある場合(例えば、エントリーレベルのデバイス向け新興市場)に残っています。Composeは宣言型構文と組み込みアニメーションのおかげで、View Systemと比較してUIコード量を30〜50%削減します。
よくある質問
はい、XMLレイアウトのComposeViewを介して可能です。Composeの依存関係を追加し、画面またはその一部をComposeView { MyComposable() }でラップします。移行は画面ごとに行います。
原因は、状態が高く引き上げられすぎているか、変更可能なオブジェクトが使用されていることです。修正:派生データにはderivedStateOf、安定した参照にはrememberを使用します。
LazyColumn(RecyclerViewに類似)を使用します。スクロールに応じて要素が作成および再利用されます。異なるセルタイプの複雑なリストの場合 — LazyColumn { items(items, key = { it.id }) { ... } }。
いいえ、Composeから直接始められます。View Systemの知識はレガシーコードの保守に役立ちますが、Composeは独自のドキュメントとパターンを持つ独立したエコシステムです。
はい、Material 3は2023年からComposeの標準テーマです。implementation("androidx.compose.material3:material3")で追加します。Material 2は非推奨と見なされています。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。