モバイル開発における Jetpack Compose: 概要、主要概念、動作の仕組み

著者: IT Sectr 公開日: 2026-07-05 読了時間: 10 分
Jetpack Compose — Google によるモダンな Android UI フレームワーク。Google Compose Docs (2025) によると、Compose は新しい Android プロジェクトの 60% で使用されています。@Composable、Recomposition、State Hoisting の理解が Compose での生産的な作業の基盤です。

主要ポイント

  • @Composable — UI 関数のアノテーション。Composition — Composable 関数の呼び出し。Recomposition — 状態変更時の再起動。
  • State Hoisting — 親への状態の引き上げ。State down, events up。再利用可能でテスト可能なコンポーネント。
  • remember + mutableStateOf — ローカル状態。remember は再コンポジション間で値を保持。
  • Modifier — 修飾子のチェーン (padding, size, clickable)。順序が重要。
  • NavController + NavHost — ナビゲーション。LaunchedEffect/DisposableEffect — 副作用。

Jetpack Compose の基礎 (@Composable, Composition, Recomposition)

@Composable — 関数を Composable に変換するアノテーション。Composable 関数は UI の構成要素です。View を返さず、Composition に要素を出力します。Composition — Composable 関数の呼び出しから構築される UI ツリー。Compose は新しいツリーを古いツリーと比較し、変更された部分のみを更新します。

Recomposition

Recomposition — 状態変更時の Composable 関数の再起動。Compose は各関数でどの状態が読み取られるかを追跡します。状態が変更されると、Compose はその状態を読み取る関数のみを再起動します (Smart Recomposition)。Recomposition は楽観的です。複数回実行される可能性があるため、関数は純粋である必要があります (副作用なし)。副作用は LaunchedEffect または DisposableEffect に記述します。Composable 関数 は suspend にできません。他の Composable 関数から呼び出されます。呼び出し順序は保証されません (Compose が並べ替える可能性があります)。

kotlin
// State Hoisting と LazyColumn を使用した Composable の例
@Composable
fun ItemList(
    items: List<String>,
    onItemClick: (String) -> Unit
) {
    LazyColumn(
        modifier = Modifier.fillMaxSize()
    ) {
        items(items) { item ->
            Card(
                modifier = Modifier
                    .fillMaxWidth()
                    .clickable { onItemClick(item) }
                    .padding(8.dp)
            ) {
                Text(
                    text = item,
                    style = MaterialTheme.typography.bodyLarge
                )
            }
        }
    }
}

@Composable
fun MainScreen() {
    var text by remember { mutableStateOf("") }
    val items = listOf("Item 1", "Item 2", "Item 3")

    Scaffold(
        topBar = {
            TopAppBar(title = { Text("Compose App") })
        }
    ) { padding ->
        ItemList(
            items = items,
            onItemClick = { selected -> text = selected }
        )
    }
}

Composition — 宣言型ツリー。Recomposition — スマートな再起動。IT Sectr は型の安定性を監視することを推奨します — 不安定な型は過剰な再コンポジションを引き起こします。

CompositionLocal

CompositionLocal — Compose での暗黙的なデータ受け渡し。SwiftUI の @Environment に類似。CompositionLocalProvider — 値の設定。current — 読み取り。用途: Theme (MaterialTheme), ContentScale, Density。静的 CompositionLocal — 変更のない設定用。動的 CompositionLocal — 可変値 (テーマ) 用。IT Sectr はグローバル設定には CompositionLocal、データには明示的パラメータの使用を推奨します。

状態 (remember, mutableStateOf, State Hoisting)

remember — 再コンポジション間で値を保持。mutableStateOf — 監視可能な状態を作成 (MutableState<T>)。変更時に再コンポジションをトリガー。State Hoisting — パターン: 状態を親コンポーネントに引き上げ、子は値とコールバックを受け取る。State (不変) — 読み取り専用。MutableState — 読み取り + 書き込み。rememberSaveable — 回転/プロセス終了時に保持。

State Hoisting

State Hoisting — 原則: state down, events up。状態は親に保存され、パラメータを介して子コンポーネントに渡されます。子コンポーネントはラムダ (コールバック) を介して変更を通知します。利点: 再利用性、テスト容易性、単一真実源。例: MyTextField が自身の状態を保存する代わりに、親が文字列を保存し、value + onValueChange を介して渡します。

派生状態

derivedStateOf — 計算された状態。依存関係が変更された場合のみ再計算。フィルタリング、変換、検証に使用。snapshotFlow — State を Flow に変換。リアクティブチェーンに使用。collectAsState — Composable 内で Flow を State に収集。IT Sectr は計算値には derivedStateOf、State とコルーチンの接続には snapshotFlow を推奨します。

コンテナ (Column, Row, Box, LazyColumn)

Column — 垂直レイアウト (LinearLayout vertical に類似)。Row — 水平レイアウト。Box — スタックレイアウト (FrameLayout に類似)。LazyColumn — 遅延読み込み付き垂直スクロールリスト。LazyRow — 水平スクロールリスト。Scaffold — メインスクリーン構造: TopAppBar, BottomBar, FloatingActionButton, Snackbar。TopAppBar — トップバー。BottomNavigation — ボトムナビゲーション (Material 3 では NavigationBar)。Modifier — チェーン: .fillMaxWidth().padding(8.dp).clickable { }。修飾子の順序が重要 — それぞれが新しいラッパーを作成します。

LazyColumn の最適化

LazyColumn — 仮想化リスト。表示要素のみをレンダリング。最適化: 1) key — アイテムの一意キー、2) contentType — タイプ別にアイテムをグループ化、3) itemContent — アイテム内の再コンポジションを最小化、4) LazyVerticalGrid / LazyHorizontalGrid — グリッド用。LazyLayout — カスタム遅延レイアウト。Paging 3 + Compose — collectAsLazyPagingItems によるページネーション。IT Sectr は予測可能な再コンポジションのためにすべての LazyColumn で key(item) を推奨します。

Navigation Compose — ナビゲーションライブラリ。NavController — デスティネーションスタックを管理。NavHost — ナビゲーショングラフのコンテナ。composable("route") — デスティネーションを登録。navController.navigate("route") — 遷移。popBackStack() — 戻る。引数: composable("detail/{id}", arguments = listOf(navArgument("id") { type = NavType.StringType }))。intentFilter によるディープリンク。BottomNavigation — NavController との統合: NavBarItem → navigate + popUpTo。

複数のバックスタック — BottomNavigation のタブごとに個別のバックスタック。SavedStateHandle — プロセス終了時に引数を保持。NavArgs — 型安全な引数 (Kotlin 2.0+)。ディープリンク — 外部リンクの URL スキーマ。予測的バックジェスチャー (Android 14+) — プレビュー付きバックジェスチャーサポート。IT Sectr は型安全性のために NavArgs、BottomNavigation には複数バックスタックの使用を推奨します。

エフェクト (LaunchedEffect, DisposableEffect)

LaunchedEffect — Composition 内で suspend ブロックを起動。Composition を離れるとキャンセル。keys が変更されると再起動。用途: データ読み込み、タイマー、アニメーション。DisposableEffect — クリーンアップが必要なリソース用: onDispose { } — リスナーの購読解除、接続を閉じる。SideEffect — 同期エフェクト (再コンポジションごと)。用途: ロギング、非 Compose コードとの同期。IT Sectr はデータ読み込みに LaunchedEffect、クリーンアップに DisposableEffect を推奨します。

パラメータ Jetpack Compose SwiftUI
UI 記述@Composable 関数 + ModifierView Protocol + @ViewBuilder
状態remember + mutableStateOf@State, @StateObject
状態の引き上げState Hoisting@Binding
リストLazyColumnList
ナビゲーションNavController + NavHostNavigationStack (iOS 16+)
エフェクトLaunchedEffect, DisposableEffect.task{}, .onAppear{}
レイアウトColumn, Row, BoxVStack, HStack, ZStack

Compose — 関数 + 修飾子。SwiftUI — struct + 修飾子。概念は類似しており、構文は異なります。IT Sectr は両方のフレームワークを学ぶことを推奨します — 一方を理解すると他方の学習が容易になります。

エフェクトパターン

rememberCoroutineScope — LaunchedEffect 外での CoroutineScope へのアクセス (例: ボタンクリック時)。snapshotFlow — チェーン用に State を Flow に変換。produceState — 非 Compose ソースを State に変換。animateFloatAsStateanimateColorAsState — エフェクトによるアニメーション。IT Sectr は UI イベントに rememberCoroutineScope、自動読み込みに LaunchedEffect を推奨します。

テーマ設定 (MaterialTheme, Material3)

MaterialTheme — Compose のグローバルテーマ。色、タイポグラフィ、形状。MaterialTheme { } — アプリ全体をラップ。Material3 (M3) — Google デザインシステム 2023+。Dynamic Colors — 壁紙に適応 (Android 12+)。TextStyle — テキスト設定: fontSize, fontWeight, lineHeight。Shape — 角の丸み。Elevation — 影。IT Sectr はデフォルトで Material3、最新デバイスには Dynamic Colors を推奨します。

kotlin
@Composable
fun AppTheme(content: @Composable () -> Unit) {
    val colorScheme = if (isSystemInDarkTheme()) {
        darkColorScheme(
            primary = Color(0xFFBB86FC),
            secondary = Color(0xFF03DAC6)
        )
    } else {
        lightColorScheme(
            primary = Color(0xFF6200EE),
            secondary = Color(0xFF03DAC6)
        )
    }
    MaterialTheme(
        colorScheme = colorScheme,
        typography = Typography(
            bodyLarge = TextStyle(fontSize = 16.sp)
        )
    ) { content() }
}

アニメーション (animate*, AnimatedVisibility)

animateFloatAsState — Float 値をアニメーション化。animateColorAsState — 色をアニメーション化。animateDpAsState — サイズをアニメーション化。AnimatedVisibility — .animateEnterExit() で表示/非表示。AnimatedContent — コンテンツ変更時のアニメーション (crossfade, slide)。updateTransition — enum 状態に基づくアニメーション。Animatable — Animatable インターフェースによるカスタムアニメーション。IT Sectr はリストに AnimatedVisibility、画面遷移に AnimatedContent を推奨します。

kotlin
@Composable
fun AnimatedCounter(count: Int) {
    val animatedCount by animateFloatAsState(
        targetValue = count.toFloat(),
        animationSpec = spring(
            dampingRatio = Spring.DampingRatioMediumBouncy,
            stiffness = Spring.StiffnessLow
        )
    )

    AnimatedContent(targetState = count) { targetCount ->
        Text(
            text = "$targetCount",
            style = MaterialTheme.typography.displayLarge,
            modifier = Modifier.animateContentSize()
        )
    }
}

テスト (Compose UI Test)

Compose UI Test — Compose 画面のテスト。createComposeRule() — JUnit ルール。setContent { } — Composable を設定。onNodeWithText, onNodeWithTag, onNodeWithContentDescription — 要素を検索。performClick, performTextInput, performScrollTo — アクション。assertIsDisplayed, assertTextEquals — アサーション。Semantics — アクセシビリティとテストのための Semantics ツリー。IdlingResource — 非同期操作の待機。スクリーンショットテスト — Papercuts, Roborazzi。IT Sectr は各画面に UI テスト、ViewModel にユニットテストを推奨します。

WindowSizeClass — 画面サイズへの適応 (Compact, Medium, Expanded)。Material3 のレスポンシブレイアウトに関連。Adaptive Navigation Suite で BottomNavigation から NavigationRail への自動切り替えに使用。IT Sectr はタブレットおよびデスクトップの Compose 適応に WindowSizeClass を推奨します。

Paging 3 + Compose — Google のページネーションライブラリ。PagingData — ページストリーム。PagingConfig — 設定 (pageSize, prefetchDistance)。collectAsLazyPagingItems() — Compose で収集。PagingSource — カスタムソース。RemoteMediator — ハイブリッド読み込み (ネットワーク + DB)。Paging 3 は Compose における無限スクロールリストの標準です。

よくある質問

Jetpack Compose の @Composable とは?

@Composable — UI 関数のアノテーション。Composable 関数の呼び出しが Composition を形成。Recomposition — 状態変更時の再起動。

Compose の State Hoisting とは?

State Hoisting — 親への状態の引き上げ。State down, events up。再利用可能でテスト可能なコンポーネント。

Jetpack Compose の Recomposition とは?

Recomposition — 状態変更時の Composable 関数の再起動。Smart Recomposition — 最小限の関数セット。

NavController と NavHost の仕組みは?

NavController — デスティネーションスタック。NavHost — グラフコンテナ。composable("route") — 登録。navigate() — 遷移。

LaunchedEffect と DisposableEffect の違いは?

LaunchedEffect — 自動キャンセル付き suspend ブロック。DisposableEffect — onDispose クリーンアップ付きリソース。

まとめ

  • @Composable — UI 関数。Composition — UI ツリー。Recomposition — スマートな再起動。
  • remember + mutableStateOf — ローカル状態。rememberSaveable — 回転時用。
  • State Hoisting — state down, events up。再利用可能なコンポーネントの基盤。
  • Modifier — チェーン (順序が重要)。Column, Row, Box — 基本コンテナ。
  • LazyColumn — 効率的なリスト。Scaffold — 画面構造 (TopBar, BottomBar, FAB)。
  • NavController + NavHost — ナビゲーション。composable() — ルート。navigate() — 遷移。
  • LaunchedEffect — 非同期エフェクト。DisposableEffect — クリーンアップ。SideEffect — 同期。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談