Cách Flutter render các Widget

Lời mở đầu

Xin chào!

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, trên con đường trở thành master fluter thì Widget chính là chìa khóa. Trong Flutter, mọi thứ đều là widget. Và vì vậy điều quan trọng là phải hiểu cách chúng hoạt động và cách Flutter hiển thị các Widget. Trong bài viết này chúng ta sẽ tìm hiểu về Element Tree, Widget Tree và Render Tree.

Widget tree

Đầu tiên là Widget tree. Widget tree được sử dụng để cấu hình Giao diện người dùng. Ở đó, bạn có thể định cấu hình các thuộc tính của Widget và định nghĩa nó sẽ hiển thị như thế nào. Tức là code mà bạn viết sẽ tạo lên widget tree.

Element tree

Cây thứ hai được gọi là Element tree. Element tree được sử dụng để quản lý và cập nhật mọi thứ. Element tree liên kết vào Widget tree, một phần tử trong Element tree là một thể hiện cụ thể của một widget. Điều này nghe có vẻ quen thuộc nếu bạn biết OOP (Lập trình hướng đối tượng) nơi bạn có các class và object trong đó các object chỉ là các thể hiện của một class.

Render Tree

Mảnh ghép còn thiếu cuối cùng là Render Object. Bên trong Render tree là các render object và về cơ bản đây là những gì bạn đang thấy trên màn hình. Bạn không thấy các widget mà bạn thấy các render object. Render object sẽ quan tâm đến kích thước, bố cục và bức tranh thực tế trên màn hình.

Cách Flutter render các widget – 3 trạng thái

Flutter trải qua 3 giai đoạn khi hiển thị các widget ra màn hình. Như chúng ta đã biết, đó không phải là những widget mà chúng ta thấy trên màn hình. Đó là các render object. Nhưng làm thế nào Flutter có thể xử lý điều này?

1. Cấu hình

Như tôi đã đề cập ở trên, widget tree chứa các widget và ở trạng thái này, tất cả là về cấu hình của các widget của chúng ta. Thông qua một API, bạn chỉ định các thuộc tính và giá trị cho các tiện ích con của mình mà cây tiện ích con sẽ nắm giữ.

2. Vòng đời

Tại đây, toàn bộ vòng đời của giao diện người dùng được quản lý. Cũng ở đây, nó xác định các thành phần hiện có trong hệ thống phân cấp giao diện người dùng của bạn. Bạn có thể hình dung trạng thái này giống như chất keo kết dính giữa trạng thái 1 và 3.

3. Vẽ

Ở đây Render tree phát huy tác dụng. Tất cả những điều liên quan về vẽ UI sẽ được thực hiện ở đây. Nó quan tâm đến các ràng buộc, phần con của các widget sẽ thực sự trông như thế nào, kích thước của chúng ra sao. Đây là nơi các render object được vẽ trên màn hình.

Ok, nhưng tại sao lại là 3 cây?

Bây giờ bạn có thể tự hỏi mình “OK Nhưng tại sao Flutter không chỉ sử dụng các widget và chỉ có một cây?”.

Thực ra đây là một câu hỏi rất hay.

Đó là về hiệu năng

Ok, điều đầu tiên.

Các widget là bất biến.

Bạn không thể thay đổi các widget. Và về cơ bản đây là lý do tại sao một widget tree là không đủ. Hãy tưởng tượng bạn thay đổi một widget Text chẳng hạn. Bạn sẽ cần một widget hoàn toàn mới bởi vì bạn không thể thay đổi cùng một widget. Và nếu bạn đang code Flutter, bạn có thể biết UI có thể thay đổi thường xuyên như thế nào.

Điều này có nghĩa là khi một widget cần thay đổi, đối tượng widget bên trong widget tree sẽ được thay thế hoàn toàn và không thể cập nhật được.

Và tại đây 2 cây còn lại phát huy tác dụng.

Cả Element và Render Tree đều được cập nhật bất cứ khi nào có thể thay vì được tạo hoàn toàn mới. Và đây là một sự cải thiện hiệu suất lớn!

Cập nhật hay không cập nhật?

Và làm thế nào Flutter quyết định xem Element và Render Object có thể được cập nhật hay không?

Hãy tưởng tượng bạn có một Widget Text, nơi bạn chỉ cần thay đổi nội dụng văn bản. Lần thứ hai bạn thay đổi nó, Phương thức CanUpdate của Widget sẽ kiểm tra hai thứ và nếu một trong số chúng là đúng, thì Render Object và Element Object sẽ được cập nhật thay vì được tạo ra các đối tượng hoàn toàn mới.

  • RuntimeType (kiểu widget như Text, Column, Container, v.v.) có còn giống nhau không?
  • Key có giống nhau không?

Trong ví dụ của chúng ta, runtimeType vẫn là Text và vì vậy nó đúng và Đối tượng phần tử sẽ gọi Phương thức updateRenderObject để đảm bảo Render Object được cập nhật thay vì được tạo lại.

Key là một thuộc tính mà bạn có thể cấp cho hầu hết mọi widget con và giúp Flutter xác định một widget con. Khá hữu ích cho mục đích này.

Và bạn có thể kiểm tra hành vi này khá dễ dàng. Khi bạn chạy một Ứng dụng Flutter bên trong IDE của mình và mở Flutter DevTools, bạn sẽ thấy chế độ xem sau:

Ở đây tôi đã chọn một widget Text và bên trong hộp màu đỏ, bạn sẽ thấy Render Object. Và Render Object này có ID bắt đầu bằng ký hiệu #. Khi bạn thay đổi nội dung văn bản cho Widget Text này, ID sẽ KHÔNG thay đổi.

Tóm lại

Flutter sẽ cố gắng sử dụng lại càng nhiều tài nguyên (các object trong cây) càng tốt trong khi cố gắng render các đối tượng mới càng ít càng tốt.

Kết luận

Flutter khá thông minh trong cách hiển thị các widget!

Bài viết này đã cung cấp và đi sâu hơn vào đặc tính và cách render UI của Flutter. Tôi hy vọng bây giờ bạn đã có thể hiểu rõ hơn về những gì xảy ra đằng sau quá trình render các Widget. Mong là bạn sẽ thích bài viết này.‌‌

1 comment

Nam April 2, 2022 - 6:11 AM

bài viết rất hữu ích

Reply

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.