Flutter 3.10: Cập nhật cách dùng MediaQuery để tránh bị rebuild không cần thiết

Ở Flutter 3.10, MediaQuery đã được cập nhật lại syntak lại chút để tránh việc bị rebuild Widget không cần thiết, thậm chí ở màn hình trước đó.

Flutter 3.10:  Cập nhật cách dùng MediaQuery để tránh bị rebuild không cần thiết

Chào bạn! Một buổi chiều ngoài trời mưa rơi tầm tã không biết làm gì nên mình ngồi xem lại kỹ hơn những thứ mới mẻ được cập nhật ở phiên bản Fluter 3.10 thì mình phát hiện 1 điều khá thú vị đã được update ở phiên bản này: MediaQuery

Mình tin là bạn, và cả mình đều sử dụng cái syntax MediaQuery.of(context).size rất là nhiều để get Size màn hình (width, height) của thiết bị hiện tại hoặc là MediaQuery.of(context).padding để phục vụ tính năng nào đó liên quan đến padding của thiết bị. Tuy nhiên việc gọi MediaQuery.of(context) như vậy cũng tiềm ẩn rất nhiều "exception" (ngoại lệ) mà bạn không ngờ tới được.

1. Vấn đề:

Ví dụ dưới đây mình sẽ show cho các bạn thấy 1 ví dụ rõ ràng nhất khi bạn sử dụng syntax trên.

Mình khởi tạo 1 project Flutter mới hoàn toàn và tạo ra 2 màn hình: HomePage & DetailPage. Bạn cũng có thể tạo project mới như mình để làm theo demo nhé!

Ở màn hình HomePage, mình đơn giản là chỉ muốn lấy ra platformBrightness hiện tại là gì và đặt log print('HomePage build'); để bất cứ lúc nào HomePage rebuild thì mình sẽ biết. Ngoài ra, ở FloatingActionButton hàm onPressed của nó mình sẽ cho navigate sang màn hình DetailPage.

Còn bên màn hình DetailPage, mình cũng đặt log print('DetailPage build'); và tạo 1 TextField Widget ở giữa màn hình.

Ok vậy là xong phần sườn rồi giờ chính thức vào phần trọng điểm của bài viết này đây. Các bạn để ý cứ mỗi lần mình focus vào TextField ở màn hình DetailPage thì màn hình HomePage lại print log 🫣.

0:00
/0:08

Có một lỗi phổ biến ở các bạn mới học Flutter thường hay đặt 1 số function (nhất là các function call API hoặc đọc file để get Data) trong hàm build, giờ các bạn đã biết thủ phạm khiến cho màn hình của mình call các function đó rồi nhé! (Lưu ý là không đặt các function như vậy trong hàm build nha, dù màn hình có bị rebuild hay không 😄).

Bạn có biết nguyên nhân tại sao màn hình HomePage bị rebuild lại chưa? Nếu chưa mình sẽ xin phép được giải đáp cho bạn luôn đó chính là mỗi khi chúng ta open/close keyboard (bàn phím), thuộc tính viewInsets trong MediaQuery sẽ bị update liên tục do sự thay đổi của padding bottom khi chúng ta tương tác với TextField. Điều đó làm ảnh hưởng luôn các nơi đang listen .context .

Vậy làm sao để fix điều trên? Không có cách nào cả nếu như bạn vẫn sử dụng các phiên bản trước Flutter 3.10

2. Giải pháp (kể từ Flutter 3.10 trở đi):

0:00
/0:08

Nếu bạn để ý, mình có thay đổi nhẹ syntax ở video trên là fix được problem trên chúng ta. Từ giờ bạn hãy thay đổi thay vì chúng ta đã quá quen với MediaQuery.of(context).platformBrightness.name thì hãy chuyển sang MediaQuery.platformBrightnessOf(context).name luôn nhé!

Nói thêm là không chỉ có mỗi platformBrightnessOf được update mà những thứ trước giờ bạn get từ MediaQuery cũng được cập nhật luôn. Ví dụ thay vì MediaQuery.of(context).size hãy đổi thành MediaQuery.sizeOf(context)

Code demo bạn tham khảo ở link bên dưới nha:

flutter_demo_on_blog/ at demo/mediaquery · Barry0501/flutter_demo_on_blog
Contribute to Barry0501/flutter_demo_on_blog development by creating an account on GitHub.

3. Lời kết:

Mình tin là với một chút thay đổi này của Flutter 3.10 sẽ cải thiện performance app của bạn đáng kể. Đừng xem thường vì những cái điều nhỏ nhặt được bạn chăm chút từng dùng code mới chính là viên gạch giúp ứng dụng của bạn chạy mượt mà hơn. Cảm ơn bạn đã xem bài viết này nhé 😘