初めに
Flutter は「ネイティブの UI コンポーネントに依存せず、同じ UI を全プラットフォームで再現できる」ことが特徴です。
その秘密は、独自のレンダリングエンジンにあります。この記事では、Flutter がどのように画面を描画しているのかを図解しながら整理します。
Flutter レンダリングの流れ
Flutter の UI は Widget ツリーから始まり、最終的に GPU 上でピクセルとして描画されます。流れは以下のとおりです。
各層の役割
-
Widget Tree
宣言的 UI。StatelessWidget や StatefulWidget で構築。 -
Element Tree
Widget のインスタンス管理とライフサイクル調整。 -
RenderObject Tree
サイズや位置を計算し、描画命令を持つ。 -
Layer Tree
再描画を効率化するための最適化済みレイヤー。 -
Skia / Impeller
低レベルのグラフィックス API を利用して描画。 -
GPU / OS Canvas
実際のピクセル出力。
Skia エンジン
-
Google が開発する 2D グラフィックスライブラリ
-
Chrome や Android の描画にも使われている
-
Flutter 初期からメインレンダラーとして採用
特徴
-
クロスプラットフォームで動作
-
高速な 2D 描画
-
CPU と GPU の両方に対応
Impeller エンジン
Flutter 3.10 から iOS でデフォルトになった新エンジンです。
特徴
-
Metal (iOS) / Vulkan (Android) に最適化
-
シェーダーを事前コンパイル → Jank(カクつき)の削減
-
将来的に Skia から完全移行予定
パフォーマンス最適化のポイント
Flutter のレンダリングは強力ですが、工夫しないとフレーム落ちが発生します。
60fps(16ms/フレーム)を維持するために意識すべきは以下です:
-
Rebuild の抑制
→ const コンストラクタ、ValueListenableBuilder の活用 -
RepaintBoundary の活用
→ 部分的な再描画を限定 -
CustomPainter
→ Skia API を直接利用して効率的に描画 -
Impeller の活用
→ iOS/Android のネイティブ GPU API に最適化
まとめ
-
Flutter は Skia / Impeller という独自レンダリングエンジンを採用
-
Widget → Element → RenderObject → Layer → GPU という流れで描画
-
Impeller により Metal/Vulkan 最適化 と Jank 削減 が進行中
-
アプリ開発者は Rebuild / Repaint 最適化 を意識することで、より滑らかな UI を実現可能