1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Android】Jetpack Compose UI ツリー vs View ツリー

Last updated at Posted at 2025-11-28

はじめに

Android の UI には、歴史的に 2つの“ツリー構造” が存在します。

  • XML / View ベースの View ツリー
  • Composable 関数から生成される Compose UI ツリー

どちらも画面 UI を構成しますが、
仕組み・更新モデル・パフォーマンス・設計思想 が根本から違います。

この記事では、
内部構造から Recomposition まで
「Android エンジニアが本当に知りたいポイント」をまとめます。


1. View ツリーとは

View ツリーは「View オブジェクトの階層構造」です。
XML を Inflate すると、以下のようなツリーが生成されます。

ViewGroup (LinearLayout)
 ├─ View (TextView)
 └─ View (Button)

特徴

  • UI は オブジェクトとして生き続ける
  • プロパティを 命令的に変更して UI を変える
  • 描画は measure → layout → draw
  • ライフサイクルは Activity/Fragment と強烈に依存
  • ViewGroup ネストが増えると重くなる

例:

Button の text を変えるときはこう:

textView.text = "OK"

→ オブジェクトに直接命令して UI を変える
→ 典型的な“命令的 UI”。


2. Compose UI ツリーとは?

Compose は「Composable 関数の結果として UI ノードができる」宣言的 UI。

Compose Root
 └─ Column (LayoutNode)
      ├─ Text (LayoutNode)
      └─ Button (LayoutNode)
            └─ Text (LayoutNode)

特徴

  • UI は「関数の呼び出し結果」であり、不変に近い
  • 状態が変わると その部分だけ再構築(Recomposition)
  • LayoutNode + ModifierNode が UI の本体
  • Android の View とは完全に独立
  • パフォーマンスは View より軽量になりやすい

例:

var text by remember { mutableStateOf("Hello") }

Button(onClick = { text = "OK" }) {
    Text(text)
}

→ text の値が変わる
→ Text() Composable だけ再構築
→ LayoutNode も該当部分だけ差し替え


3. 更新モデルの違い:ここが最重要!

3.1 View:オブジェクトを書き換える(命令的)

View ツリーの更新は 状態とは無関係

textView.text = "OK"
button.isEnabled = false

このように:

  • プロパティを直接 mutate
  • View 自体は生き続ける
  • レイアウトパス(measure/layout/draw)が走る

3.2 Compose:状態が変われば再構築(宣言的)

状態を UI に反映するための唯一の手段は:

Composable を再呼び出す(Recompose)こと

text = "OK"  // ← 値が変わる
↓
Text(text) が再呼び出される(Recomposition)
↓
該当する LayoutNode だけ差し替え
↓
画面が変わる

状態が UI を作る → React のようなモデル
だが React より速い。理由は:

  • 差分を Runtime が把握している
  • Virtual DOM を持たない
  • Slot Table により “何がどの状態に依存するか” を追跡している

4. パフォーマンスモデルの違い


4.1 View は「重い」

View は:

  • 一つ一つが巨大オブジェクト
  • measure/layout がコスト高
  • ViewGroup がネストするとさらに遅い

4.2 Compose は「軽量で効率的」

内部構造(オリジナル図):

Composable()
  ↓
Slot Table(記録)
  ↓
LayoutNode(軽量 UI ノード)
  ↓
ModifierNode(責務のパイプライン化)

理由:

  • LayoutNode は超軽量
  • ModifierNode は必要な機能だけを積む
  • 不要ノードは Recomposition で作られない
  • スロットテーブルによる“差分再構築”

結果:

→ 中〜大規模 UI ほど Compose の強さが出る
→ アニメーションや状態更新が滑らか


5. どう共存するの?(Interop 重要)

5.1 View に Compose を挿入(ComposeView)

ComposeView(context).setContent {
    Text("Hello Compose")
}

View ツリーの中に:

ViewGroup
 └─ ComposeView
      └─ Compose UI ツリー

5.2 Compose に View を挿入(AndroidView)

AndroidView(factory = { context ->
    WebView(context)
})

Compose UI ツリーの中に:

Compose Root
 └─ AndroidView
      └─ View ツリー

6. 全体まとめ

比較項目 Compose UI ツリー View ツリー
UI の実体 LayoutNode / ModifierNode View / ViewGroup
UI の生成 関数実行 オブジェクト生成
主な更新 Recomposition(差し替え) プロパティ変更
描画パイプライン Compose 独自 measure/layout/draw
メモリ効率 高い 重い
状態管理 宣言的(State → UI) バラバラ(UI が State を持つ)
ライフサイクル 独立 Activity/Fragment と密接
カスタム UI Modifier / Layout Custom View

7. 結論:Compose が現代 UI の本命である理由

Compose UI ツリーは:

  • 関数式で安全
  • 状態と UI の同期が自然
  • パフォーマンスが現代的
  • 再利用性が高い
  • モジュール化しやすい
  • テストしやすい

View ツリーはレガシーに見えるかもしれないけど:

  • MapView / WebView など重 UI は依然必要
  • レガシーとの兼ね合いでは共存が最善策

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?