Shuhaib
Flutter内部構造
Aug 24, 2026読了時間 7分

Flutterの3つのツリー構造を徹底解剖: Widget、Element、RenderObject

不変のWidgetツリー、永続的なElementツリー、描画計算を行うRenderObjectツリーの関係性を紐解き、Flutterが画面描画を行う真の仕組みを解き明かします。

SK

Shuhaib KT

Flutter & Mobile Engineer

下記の技術解説コードおよび詳細な実装内容は、英語の原本に基づいて掲載されています。

If you've written Flutter for more than five minutes, you've heard the famous mantra: 'Everything is a Widget.' But if you take a look at how Flutter actually renders pixels on a screen at 120 FPS, widgets are only the tip of the iceberg.

In reality, Flutter runs three parallel trees simultaneously: the Widget Tree, the Element Tree, and the RenderObject Tree. Understanding how these three trees coordinate is the single biggest unlock for understanding Flutter's performance model.

The 3 Roles at a Glance

  • Widget Tree (The Blueprint): Extremely cheap, immutable configuration classes that are created, torn down, and garbage-collected constantly without performance penalty.
  • Element Tree (The Manager): The long-lived structural spine of your app. Elements hold memory pointers, manage lifecycle, and perform reconciliation diffing via canUpdate().
  • RenderObject Tree (The Painter): Heavyweight layout and paint engine that calculates exact sizes, hit-tests touches, and draws pixels to Skia/Impeller canvas.

Interactive Architecture Simulator

Use the interactive lab below to watch a StatelessWidget lifecycle step-by-step. Notice how rebuilding with identical text triggers zero RenderObject repainting!

Desktop View Recommended

Please use a desktop or laptop screen to view the full side-by-side interactive Flutter architecture visualizer.

Flutter's Three Trees Pipeline

/Stateless Lifecycle

Widget (Blueprint) → Element (Manager) → RenderObject (Painter)

CONTROL PANELLive Triggers
DEVICE PREVIEW60 FPS

No widget mounted (empty scaffold)

3-TREE VISUALIZER STAGETrees Empty
Widget Tree

Blueprints · Disposable

awaiting build()
Cheap to create & throw away
Element Tree

Managers · Persistent

no element mounted
Survives across all rebuilds
RenderObject Tree

Painters · Layout & Paint

nothing to paint
Heavy mutable drawing node
Widget (Blue)Element (Green)RenderObject (Orange)
Rule: runtimeType == runtimeType && key == key
framework.log
Flutter Engine
IDLE00:00:00
Framework Ready

Ready. Click Step 1 to mount the widget.

Stateless ReconciliationSynchronized

How canUpdate() Saves Your Frame Budget

When a parent widget rebuilds, Flutter checks whether the existing Element can be preserved using a static comparison function:

dart
static bool canUpdate(Widget oldWidget, Widget newWidget) {
  return oldWidget.runtimeType == newWidget.runtimeType
      && oldWidget.key == newWidget.key;
}

If canUpdate() returns true, Flutter does not allocate a new Element or destroy the RenderObject. It simply updates the Element's internal reference pointer to the new widget blueprint and calls updateRenderObject() only if data changed.

Because RenderObjects are expensive C++ / Dart objects that compute trigonometry and text metrics, reusing them via Element persistence is why Flutter achieves silky-smooth animations.

タグ:#Flutter#Architecture#Rendering Engine#Performance#Dart
SK

Shuhaib KT による執筆

Flutter & Mobile Engineer

クラウドバックエンド(FastAPI/NestJS/AWS)、高性能Next.js Webフロントエンド、オフライン対応Flutterアプリの設計・構築を専門とするフルスタックエンジニア。

関連記事