- vừa được xem lúc

[Flutter] - Sử dụng Keys trong Flutter [1]

0 0 491

Người đăng: Quokka Mouse

Theo Viblo Asia

Nguồn

Tham số Key có thể xuất hiện ở hầu hết mọi widget trong Flutter, nhưng việc sử dụng chúng lại ít phổ biến. Các key này sẽ giữ state của widget và định vị chúng trong WidgetTree. Trong thực tế, chúng hữu ích trong việc xác định vị trí cuộn của người dùng hoặc giữ trạng thái khi ta sửa đổi collection chứa các widget.

Ví dụ về Key

Hầu hết, bạn không cần đến Key trong tất cả các Widget của mình ! Nói chung là không cần đến chúng cũng được, giống như từ khóa new hoặc việc khai báo các type ở cả bên phải và bên trái của một biến (Ví dụ: Map<Foo, Bar> aMap = Map<Foo, Bar>()). Nhưng, nếu trong trường hợp thêm, xóa hoặc sắp xếp lại một collection các widget cùng loại có state thay đổi, bạn có thể phải dùng đến Key!

Quokka sẽ viết một ứng dụng đơn giản với 2 Widget có màu ngẫu nhiên hoán đổi vị trí khi nhấn vào button:

Trong phiên bản Stateless của ứng dụng, Quokka có hai StatelessTiles, mỗi ô có một màu được tạo ngẫu nhiên, trong một Row và tạo một Stateful PositionedTiles để lưu trữ vị trí của các ô này. Khi Quokka ấn vào FloatingActionButton, PositionedTiles sẽ hoán đổi vị trí của chúng trong list bằng phương thức setState:

class PositionedTiles extends StatefulWidget { @override State<StatefulWidget> createState() => PositionedTilesState();
} class PositionedTilesState extends State<PositionedTiles> { List<Widget> tiles = [ StatelessColorfulTile(), StatelessColorfulTile(), ]; @override Widget build(BuildContext context) { return Scaffold( body: Row(children: tiles), floatingActionButton: FloatingActionButton( child: Icon(Icons.sentiment_very_satisfied), onPressed: swapTiles), ); } swapTiles() { setState(() { tiles.insert(1, tiles.removeAt(0)); }); }
} class StatelessColorfulTile extends StatelessWidget { Color myColor = UniqueColorGenerator.getColor(); @override Widget build(BuildContext context) { return Container( color: myColor, child: Padding(padding: EdgeInsets.all(70.0))); }
}

Nhưng nếu Quokka thay StatelessColorfulTile bằng StatefulColorfulTile và lưu Color trong State. Chạy lại và nhấn button thì có vẻ như không có gì xảy ra? Why ??

List<Widget> tiles = [ StatefulColorfulTile(), StatefulColorfulTile(),
]; ...
class StatefulColorfulTile extends StatefulWidget { @override ColorfulTileState createState() => ColorfulTileState();
} class ColorfulTileState extends State<ColorfulTile> { Color myColor; @override void initState() { super.initState(); myColor = UniqueColorGenerator.getColor(); } @override Widget build(BuildContext context) { return Container( color: myColor, child: Padding( padding: EdgeInsets.all(70.0), )); }
}

Xin nhắc lại, đoạn code hiển thị ở trên bị lỗi ở chỗ: nó không hiển thị màu sắc bị hoán đổi khi người dùng nhấn vào button. Cách khắc phục cho vấn đề này là thêm một tham số Key vào các widget state:

List<Widget> tiles = [ StatefulColorfulTile(key: UniqueKey()), // Keys added here StatefulColorfulTile(key: UniqueKey()),
]; ...
class StatefulColorfulTile extends StatefulWidget { StatefulColorfulTile({Key key}) : super(key: key); // NEW CONSTRUCTOR @override ColorfulTileState createState() => ColorfulTileState();
} class ColorfulTileState extends State<ColorfulTile> { Color myColor; @override void initState() { super.initState(); myColor = UniqueColorGenerator.getColor(); } @override Widget build(BuildContext context) { return Container( color: myColor, child: Padding( padding: EdgeInsets.all(70.0), )); }
}

Nhưng, điều này chỉ cần thiết nếu bạn có các Widget có Stateful trong Subtree mà bạn đang sửa đổi. Nếu toàn bộ subtree widget trong collection của bạn là Stateless , các Key không cần thiết. Đó là tất cả những gì bạn cần biết để sử dụng Key trong Flutter. Nhưng nếu bạn muốn hiểu chi tiết hơn thì tại sao lại như vậy?

Sự khó chịu của Key đôi khi lại cần thiết

Quokka tiến hành "zoom" to một Widget, ta sẽ thấy Flutter xây dựng một Element tương ứng với widget đó. Khi xây dựng một WidgetTree, Flutter cũng xây dựng một ElementTree. Chỉ là ElementTree này đơn giản hơn, nó chỉ chứa thông tin về Type của từng Widget và tham chiếu đến các Element con. Bạn có thể nghĩ ElementTree giống như một bộ xương của ứng dụng Flutter. Row widget trong ví dụ trên về cơ bản chứa một tập hợp các vị trí được đặt cho mỗi con của nó. Khi Quokka trao đổi thứ tự của các TileWidget trong Row, Flutter sẽ kiểm tra ElementTree xem cấu trúc khung xương cũ và mới có giống nhau không.

Bắt đầu với RowElement, và sau đó đến con của nó. Flutter sẽ kiểm tra xem widget mới có cùng type và key với element cũ hay không, và nếu giống, nó sẽ cập nhật tham chiếu của nó tới widget đó. Trong phiên bản stateless, các widget không có key, vì vậy Flutter chỉ kiểm tra type (xem hình). Cấu trúc của ElementTree cho các StatefulWidget trông hơi khác. Có các widget và các element như trước đây, nhưng có thêm một cặp state objects đi cùng chứa thông tin về Color.

Trong trường hợp TileStateful không có Key, khi Quokka đổi thứ tự của hai Widget, Flutter duyệt ElementTree, kiểm tra Type của RowWidget và cập nhật tham chiếu. Sau đó TileElement kiểm tra xem widget tương ứng có cùng loại (TileWidget) hay không, sau đó nó cập nhật tham chiếu. Điều tương tự cũng xảy ra với child thứ hai. Bởi vì Flutter sử dụng ElementTree và State tương ứng của nó để xác định những gì thực sự sẽ hiển thị trên thiết bị, và vì thế, trong trường hợp này, các widget đã không được hoán đổi đúng cách!

Trong phiên bản đã sửa lỗi với StatefulTiles, Quokka đã thêm param Key cho các widget. Bây giờ chúng ta trao đổi các widget như trước, nhưng giờ Key của TileElement không khớp với khóa của TileWidget tương ứng. Điều này khiến Flutter hủy kích hoạt các element đó và xóa các tham chiếu đến các TileElement trong ElementTree, bắt đầu với element đầu tiên không khớp.

Sau đó, Flutter xét children element của RowElement, tìm và tham chiếu đến Widget có Key tương ứng. Flutter làm điều tương tự cho child thứ hai. Và thế là Flutter sẽ hiển thị những gì Quokka mong đợi, với các Widget hoán đổi vị trí và cập nhật màu sắc khi nhấn button.

Tóm lại, Key sẽ hữu ích nếu bạn tác động đến vị trí của các stateful widget trong collection như trong ví dụ trên. Thông thường, state phức tạp hơn nhiều. Việc phát animation, hiển thị dữ liệu mà người dùng đã nhập và vị trí scroll đều liên quan đến state.

Tiếp theo

Ở phần tiếp theo, Quokka sẽ đề cập đến việc sử dụng Key ở đâu, và các loại Keys được sử dụng trong Flutter cũng như các trường hợp áp dụng của chúng.

Cảm ơn bạn vì đã đọc ! ❤️

Bình luận

Bài viết tương tự

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 1: Làm quen cô nàng Flutter

Lời mở đầu. Gần đây, Flutter nổi lên và được Google PR như một xu thế của lập trình di động vậy.

0 0 281

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 3: Lột trần cô nàng Flutter, BuildContext là gì?

Lời mở đầu. Màn làm quen cô nàng FLutter ở Phần 1 đã gieo rắc vào đầu chúng ta quá nhiều điều bí ẩn về nàng Flutter.

0 0 218

- vừa được xem lúc

Dart Cheat Sheet - Full bộ "bỏ túi" các syntax trong ngôn ngữ Dart

Dart là một ngôn ngữ mới dùng cho cả Mobile và Web với Flutter Framework, thậm chí dùng cho Backend. Để giúp mọi người dễ dàng nắm bắt ngôn ngữ này hơn, 200lab Education đã tổng hợp thành bộ "bí tịch" dưới đây để tra cứu nhanh, tăng tốc phát triển phần mềm.

0 0 51

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 2: StatefulWidget vs StatelessWidget. Khi nào thì cần sử dụng cái nào?

Lời mở đầu. Ở bài trước, chúng ta đã dừng lại ở một kết thúc mở.

0 0 96

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 4: Lột trần InheritedWidget

Lời mở đầu. Trong đoạn kết của phần 2, chúng ta đã đối mặt với 1 bài toán: Làm thế nào để truyền data từ một widget cha nào đó xuống thẳng widget chắt mà không phải sử dụng constructor để truyền xuống

0 0 67

- vừa được xem lúc

Chinh phục RxDart Flutter trong 3 nốt nhạc. Nốt thứ nhất: Stream và giải thích các thuật ngữ

Lời mở đầu. Mình viết series này với mục đích chia sẻ kiến thức về RxDart trong Flutter.

0 0 74