Flutter tách UI thành ba cây với vai trò khác nhau: widget là bản mô tả, element là "phiên bản đang sống" giữ vị trí và state, render object lo layout và vẽ.
- Widget tree: object bất biến, rẻ, được tạo lại mỗi lần
build(). Nó chỉ là cấu hình ("nút màu xanh, chữ OK"). - Element tree: mỗi widget được gắn vào cây qua một
Element. Element sống lâu, giữ tham chiếu tới widget hiện tại, tớiState(vớiStatefulWidget) và tới render object.BuildContextchính là element. - Render tree: các
RenderObjecttính kích thước, vị trí (layout) và vẽ (paint). Tạo chúng tốn kém nên Flutter cố tái sử dụng.
Khi gọi setState(), element bị đánh dấu dirty → frame kế tiếp gọi lại build() ra widget mới → element so widget mới với cũ bằng Widget.canUpdate (cùng runtimeType và cùng key):
- Khớp → giữ element và render object, chỉ cập nhật thuộc tính; render object chỉ markNeedsLayout/markNeedsPaint khi thuộc tính đó thực sự đổi.
- Không khớp → huỷ subtree cũ, tạo element và render object mới (state bên trong mất).
Nhờ vậy "rebuild" widget rẻ: phần đắt (layout, paint) chỉ chạy ở chỗ thực sự thay đổi.
Lưu ý: state của StatefulWidget nằm trong element, không nằm trong widget. Đổi kiểu widget hoặc đổi key ở cùng vị trí sẽ làm mất state — đây là lý do cần Key khi danh sách đổi thứ tự.