Key giúp Flutter nhận ra "đây vẫn là widget cũ" khi vị trí của nó trong danh sách con thay đổi. Element so widget mới với cũ bằng Widget.canUpdate: cùng runtimeType và cùng key. Không có key, Flutter chỉ so theo kiểu + vị trí.
Lỗi hay gặp: danh sách TodoItem là StatefulWidget (trạng thái checkbox nằm trong State). Xoá item đầu → item thứ hai trượt lên vị trí 0, Flutter thấy cùng kiểu nên giữ element và State cũ ở vị trí 0 → checkbox của item đã xoá "dính" sang item khác.
ListView(
children: [
for (final todo in todos)
TodoItem(key: ValueKey(todo.id), todo: todo),
],
)Các loại key:
- ValueKey: dựa trên một giá trị duy nhất (id) — dùng nhiều nhất.
- ObjectKey: dựa trên identity của object khi không có id riêng.
- UniqueKey: mỗi lần tạo là key mới → buộc tạo lại widget (reset state).
- GlobalKey: duy nhất toàn app, cho phép truy cập State từ bên ngoài (formKey.currentState!.validate()) hoặc chuyển widget sang chỗ khác trong cây mà vẫn giữ state. Tốn kém hơn, chỉ dùng khi thật cần.
Lưu ý: key chỉ cần khi widget stateful (hoặc có animation) bị thêm/xoá/đổi thứ tự trong cùng danh sách con; danh sách chỉ hiển thị dữ liệu stateless thì không cần. Đừng dùng index làm ValueKey — index đổi khi xoá item nên không giải quyết được gì.