aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
SAVED POSTS
aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
aedev.net
No Result
View All Result
Minh họa phát triển ứng dụng mobile đa nền tảng với Flutter

Flutter ValueKey: giữ state đi cùng dữ liệu khi đảo thứ tự danh sách

Suong Nguyen by Suong Nguyen
26/10/2026
in Flutter
0
585
SHARES
3.2k
VIEWS
Summarize with ChatGPTShare to Facebook

Bạn tăng bộ đếm ở một hàng rồi đảo danh sách. Nhãn của hàng di chuyển nhưng bộ đếm dường như vẫn nằm ở vị trí cũ. Nếu state được giữ local trong từng StatefulWidget, hãy xem cách framework nhận diện các hàng khi dựng lại cây.

Bài này dùng Column có hai hàng để quan sát mối liên hệ giữa dữ liệu và state. Tài liệu Flutter được đối chiếu ngày 26/10/2026. Code đã được rà theo API nhưng chưa build hoặc chạy widget test trong lượt biên tập; không có kết quả chạy thiết bị giả định trong bài.

1. Key là định danh tại một vị trí trong cây

Widget.key giải thích việc framework so sánh runtimeType và key khi cập nhật element. ValueKey dùng giá trị để nhận diện và phù hợp với dữ liệu có ID ổn định khi danh sách thay đổi.

Trong ví dụ, hai Item có ID a và b. Nhãn chỉ phục vụ hiển thị. Nếu nhãn được đổi trong tương lai, bạn vẫn muốn state gắn với cùng ID, không tự đổi sang một mục khác chỉ vì dòng chữ đã khác.

2. Một ví dụ đủ để thử đảo thứ tự

Đặt vào lib/main.dart của dự án Flutter thử:

import 'package:flutter/material.dart';

void main() => runApp(const MaterialApp(home: KeyDemo()));

class Item {
  const Item(this.id, this.label);
  final String id;
  final String label;
}

class KeyDemo extends StatefulWidget {
  const KeyDemo({super.key});
  @override
  State<KeyDemo> createState() => _KeyDemoState();
}

class _KeyDemoState extends State<KeyDemo> {
  List<Item> _items = const [Item('a', 'Backend'), Item('b', 'Mobile')];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Key và thứ tự')),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            FilledButton(
              onPressed: () => setState(() {
                _items = _items.reversed.toList();
              }),
              child: const Text('Đảo thứ tự'),
            ),
            for (final item in _items)
              CounterTile(key: ValueKey(item.id), label: item.label),
          ],
        ),
      ),
    );
  }
}

class CounterTile extends StatefulWidget {
  const CounterTile({super.key, required this.label});
  final String label;
  @override
  State<CounterTile> createState() => _CounterTileState();
}

class _CounterTileState extends State<CounterTile> {
  int _count = 0;
  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text('${widget.label}: $_count'),
      trailing: IconButton(
        tooltip: 'Tăng ${widget.label}',
        onPressed: () => setState(() => _count += 1),
        icon: const Icon(Icons.add),
      ),
    );
  }
}

State bộ đếm nằm trong CounterTile; parent chỉ quản lý thứ tự và dữ liệu nhãn. Cách bố trí này cố ý làm tác động của key dễ quan sát. Nếu bộ đếm đã được lưu ở một store khác theo ID, tình huống cần chẩn đoán sẽ khác.

3. Thực hiện phép thử có đối chứng

Tăng Backend lên một giá trị dễ nhớ rồi bấm đảo. Với ValueKey theo ID, kỳ vọng bộ đếm tiếp tục đi cùng Backend. Sau đó thử một bản riêng bỏ đối số key và khởi động lại state của demo trước khi quan sát lần nữa.

Không trộn kết quả giữa hot reload và một phiên state mới khi bạn đang đổi cách nhận diện widget. Ghi rõ bản code, thao tác và nhãn đang giữ bộ đếm. Tài liệu ValueKey có minh họa cùng vấn đề nhận diện khi reorder; bài chưa khẳng định đã chạy đối chứng trên một SDK cụ thể.

4. Chọn key ổn định và đặt đúng cấp

ID nên ổn định, duy nhất giữa các mục cùng parent và gắn với thực thể bạn muốn giữ state. Dùng index làm key khi index đổi theo reorder sẽ không diễn đạt cùng ý định đó. Dùng nhãn có thể trùng hoặc được chỉnh sửa cũng cần cân nhắc lại hợp đồng dữ liệu.

Trong cây mẫu, CounterTile là child trực tiếp của Column nên key được đặt tại đó. Nếu sau này bọc mỗi hàng bằng một Padding ở cấp danh sách, hãy xem child nào đang được đối chiếu ở cấp đó. Chỉ đặt key sâu hơn trong một cây con không tự làm mọi ancestor nhận diện đúng các hàng.

Đừng dùng UniqueKey mới trong mỗi lần build để “bảo đảm duy nhất” khi mục tiêu là giữ định danh qua các frame. UniqueKey chỉ bằng chính nó; tạo đối tượng mới có thể khiến framework xem đó là child mới và tạo state mới.

Key không thay thế quản lý dữ liệu

ValueKey không tự lưu state qua việc ứng dụng bị hủy process hay đồng bộ dữ liệu với server. Nó cũng không chữa việc hai bản ghi dùng cùng ID hoặc parent cung cấp sai dữ liệu. Hãy xác định phạm vi vấn đề trước: nhận diện element, vòng đời màn hình hay lưu trữ lâu dài.

Với danh sách dựng lười hoặc nhiều cấp state phức tạp hơn Column, cần đọc thêm API của widget cụ thể. Không suy ra rằng thêm một key bất kỳ sẽ giữ mọi cây con tồn tại vô thời hạn ngoài vùng hiển thị.

Kiểm tra và lỗi thường gặp

Thử đảo hai lần, thêm một mục mới và đổi nhãn của một ID trong bản demo mở rộng. State mong đợi cần được mô tả theo ID. Nếu hai hàng trao đổi bộ đếm, rà key ở cấp sibling; nếu bộ đếm luôn về 0, tìm key bị tạo lại hoặc child bị loại khỏi cây.

Kiểm tra duplicate key trước khi tìm mẹo tối ưu rebuild. Một thông báo key trùng thường là tín hiệu dữ liệu hoặc cách gắn key cần sửa, không phải lý do chuyển sang key ngẫu nhiên để bỏ qua lỗi.

Kết luận

Key ổn định giúp framework duy trì mối liên hệ giữa element và dữ liệu khi cấu trúc thay đổi. Bắt đầu bằng một phép thử hai hàng rồi đặt key theo ID ở đúng cấp, thay vì thêm key như một thuộc tính trang trí.

Nguồn tham khảo

  • Flutter: Widget.key
  • Flutter: ValueKey
  • Flutter: UniqueKey

Tags: FlutterStateValueKey
SummarizeShare234
Suong Nguyen

Suong Nguyen

Related Stories

Minh họa phát triển ứng dụng mobile đa nền tảng với Flutter

Flutter Form: validate dữ liệu trước khi gọi save

by Suong Nguyen
25/10/2026
0

Tổ chức Form và TextFormField với GlobalKey ổn định, validator rõ ràng và luồng validate rồi save có thể kiểm tra.

Minh họa phát triển ứng dụng mobile đa nền tảng với Flutter

TextEditingController trong Flutter: giữ nội dung và con trỏ đúng vòng đời

by Suong Nguyen
24/10/2026
0

Tổ chức TextEditingController trong State, cập nhật text và selection cùng lúc, tránh reset nội dung khi widget rebuild.

Minh họa phát triển ứng dụng mobile đa nền tảng với Flutter

ValueNotifier trong Flutter: cập nhật list để giao diện nhận đúng thay đổi

by Suong Nguyen
23/10/2026
0

Hiểu cách ValueNotifier dùng phép so sánh bằng, cập nhật list bằng giá trị mới và quản lý vòng đời notifier rõ ràng.

Minh họa phát triển ứng dụng mobile đa nền tảng với Flutter

Tìm kiếm Flutter: debounce và chặn response cũ ghi đè kết quả mới

by Suong Nguyen
22/10/2026
0

Kết hợp Timer, mã phiên truy vấn và kiểm tra mounted để màn hình tìm kiếm không hiển thị nhầm kết quả khi mạng trả về lệch thứ...

0 0 votes
Article Rating
Subscribe
Login
Notify of
guest
guest
0 Comments
Oldest
Newest Most Voted
AE Dev

AE Dev mang đến các bài viết về lập trình, mobile app, backend, frontend, WordPress và công nghệ, phù hợp cho developer muốn học hỏi và cập nhật kiến thức thực tế.

Recent Posts

  • React Native Image: cover và contain khác nhau trong cùng một khung ảnh
  • JavaScript sort: vì sao số 10 đứng trước 2 và mảng gốc bị đổi?
  • Android plurals: vì sao getQuantityString cần truyền count hai lần?

Categories

  • AI
  • Backend
  • Đánh giá
  • DevOps
  • Flutter
  • Hướng dẫn
  • Lập trình Mobile
  • Phỏng vấn
  • React Native
  • Uncategorized

Weekly Newsletter

  • Buy JNews
  • Support Forum
  • Pre-sale Question
  • Contact Us

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In
No Result
View All Result
  • Trang chủ
  • AI
  • Mobile
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
  • Flutter

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

wpDiscuz
0
0
Would love your thoughts, please comment.x
()
x
| Reply