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

[Flutter] Bản chất của cập nhật giao diện trong Flutter

0 0 25

Người đăng: Vịnh Ngô

Theo Viblo Asia

I. Giới thiệu

Xin chào các bạn, hôm nay chúng ta cùng tìm hiểu và phân tích cách mà giao diện được xây dựng như thế nào nhé. Let’s go. 👉🏻

II. Công thức của giao diện

1. Giao diện và dữ liệu

  • Giao diện là thành phần hiển thị mà người dùng có thể xem, có thể tương tác để nhận biết thông tin và trao đổi thông tin với ứng dụng/hệ thống.
  • Các thành phần cơ bản của giao diện như chữ (Text), hình ảnh (Image), màu sắc (Color), bảng (Table)… rất là nhiều luôn.
  • Các giao diện trên muốn hiển thị cho có ý nghĩa thì nó cần nội dung gọi là dữ liệu hay nói cách khác giao diện phụ thuộc vào giữ liệu.
    • Ví dụ:
      • Text thì cần nội dung, style
      • Image cần đường dẫn
      • CheckBox cần trạng thái đã chọn hoặc bỏ chọn

Vậy chúng ta có thể rút ra được công thức dự trên công thức toán học:

y=f(x) y = f(x)

  • y : Giao diện
  • x: Dữ liệu

**⇒ Giao diện = f(Dữ liệu) **

Dữ liệu biến thiên làm cho Giao diện cũng thay đổi =))

Vậy hàm f ở đây là gì?

Việc sắp xếp các Widget trong Flutter lại với nhau để chúng hiển thị lên màn hình được coi như việc tạo nên các bảng thiết kế, nó đóng vai trò như là hàm f.

2. Cập nhật lại giao diện

  • Như đã biết tại một thời điểm nhất định thì chúng ta có dữ liệu nhất định và có giao diện nhất định.
  • Muốn giao diện thay đổi thì cần phải biết dữ liệu thay đổi.

Câu hỏi đặt ra: Làm sao để biết dữ liệu thay đổi?

Trong lập trình cũng như trong cuộc sống, cách mà để chúng ta nhận biết được có sự vật, sự việc thay đổi thường có 2 cách.

  1. Một là chúng ta tự đi xem tình trạng của việc/vật đó như thế nào.
  2. Hai là có *cái gì đó tới báo động cho chúng ta biết trạng thái của việc/vật đó như thế nào.

Yah đúng vậy, trong các framework sẽ được cung cấp cách để làm mới lại giao diện khi có sự thay đổi. (Mặc dù ko có thay đổi làm mới cũng được, chỉ có điều hơi bị lãng phí tài nguyên 1 chút hehe)

3. Declarative và Imperative programming

📌 Phần này mình xin phép giải thích dựa trên hiểu biết của mình và khía cạnh về lập trình giao diện nhé.

💬 Trong lập trình Flutter thì cách xây dựng UI phụ thuộc vào State được gọi là declarative. Ở một số framework (như Android SDK hoặc iOS UIKit …) được gọi là imperative. (Cá nhân mình gọi là cách lập trình giao diện hồi xưa, để mình giải thích 1 xíu nhé.)

Về imperative:

Hiểu như sau:

Khi bạn lập trình giao diện chẵn hạn như là hiển thị 1 đoạn văn bản Text thì để gán dữ liệu cho Text này chúng ta cần cung cấp cho Text này một id hoặc 1 cách nào đó để định danh được Text này.

Từ id chúng ta sẽ lấy được đối tượng Text này và từ đó dùng hàm ví dụ hàm setText để gán giá trị thì UI sẽ được cập nhật.

/*Đoạn mã này không nằm trong ngôn ngữ, framework nào cả, mình chỉ làm mã giả để minh họa cho mọi người dễ hiểu thôi ạ*/ //Ví dụ bằng mã nguồn
var Text text = Text(id: 'my_text', text: 'Hello World'); //xài ông này gắn lên giao diện ở đâu đó 
//và nó hiển thì là 'Hello World' //để lấy được text theo id
var myText= Text.findById('my_text');
myText.setText('Happy New Year');
//bây giờ được cập nhật thành 'Happy New Year'

Về declarative:

Trong Flutter dữ liệu mà để hiển thị lên giao diện được gọi là state. Khi muốn làm mới lại giao diện thì chúng ta gọi hàm setState().

*note: nếu bạn chưa biết setState() là gì thì có thể vào tài liệu của flutter để đọc nhé: Link

class SampleWidget extends StatefulWidget { const SampleWidget({Key? key}) : super(key: key);  _SampleWidgetState createState() => _SampleWidgetState();
} class _SampleWidgetState extends State<SampleWidget> { String text = 'Hello World';  Widget build(BuildContext context) { return Column( children: [ //InkWell là một widget có thể tương tác chạm //Mình gọi là một cái nút InkWell( onTap: () { text = 'Happy New Year'; setState(() {}); }, child: Text('Nhấn nút'), ), //Text hiển thị văn bản //Lần đầu Text này sẽ hiển thị là Hello World //Khi nút InkWell bên trên thì //nội dung text bên dưới này đổi lại thành Happy New Year Text(text), ], ); }
}

Wow nhìn có ví dụ thì chúng ta có thể thấy declarative không quan tâm tới vị trí hay định danh của giao diện, nó chỉ cần biết gọi setState thì giao diện được cập nhật.

Một số nhận xét:

  • 2 cách thiết kế giao diện thuộc 2 trường phái khác nhau.
  • Về việc code thì declarative có vẻ nhàn hơn.
  • Nhưng so về hiệu năng thì imperative tốt hơn vì nó chỉ thay đổi nơi cần thay đổi.

🚀 Yah nhưng các bạn đừng quá lo lắng về phần hiệu năng vì các nhà phát triển của Google đã làm rất tốt trong việc tối ưu hiệu năng rồi. Mặc dù như thế việc setState bừa bãi sẽ làm ảnh hưởng tới hiệu năng của ứng dụng nên mới sinh ra nhiều state managment như hiện nay nào là Provider, Bloc, GetX, RiverPod…

III. State Management

📌 Các bạn có thể vào trang https://docs.flutter.dev/development/data-and-backend/state-mgmt/options để xem các thư viện được recommend nhé.

Cá nhân mình thấy mỗi thư viện đều có cái hay riêng. Nếu không làm theo công ty/doanh nghiệp/nhóm yêu cầu 1 cái cụ thể thì bạn hãy trãi nghiệm càng nhiều thư viện để tự đưa ra đánh giá nhé.

Cá nhân mình đưa ra một số điểm như sau để đánh giá:

  1. Viết code nhiều hay ít/nhanh hay chậm
  2. Có dễ viết theo tư tưởng/tư duy lập trình của bản thân mình hay không
  3. Code có dễ tách rời và mở rộng hay không
  4. Có dễ bảo trì và sữa lỗi hay không
  5. Thư viện có cộng đồng support nhiều/nhanh chóng hay không

💯 Thực ra các state management nó không chỉ đơn giản là quản lý state để build lại giao diện mà các bạn hãy đọc hiểu cơ chế, mô hình mà thư viện đó xây dựng để có cái nhìn sâu sắc hơn về lập trình nhé.

IV. setState king of state management

The low-level approach to use for widget-specific, ephemeral state.

setState là cách đơn giản nhất để làm mới lại toàn bộ giao diện trong 1 State của StatefullWidget.

Như cơ chế ở phần II. 2 mình đã đề cập ở các thư viện thì sâu bên trong nó có một nơi để lắng nghe sự thay đổi của dữ liệu và khi dữ liệu được lắng nghe bên trong nó sẽ gọi hàm setState để cập nhật lại giao diện.

Ứng dụng cơ chế này vào các hàm builder như BlocBuilder (Flutter_Bloc), GetBuilder, Obx (GetX), StreamBuilder, FutureBuilder, ValueListenableBuilder... các class Widget này thường là StatefulWidget. Tại hàm initState (Thường là ở initState) sẽ tạo một sự kiện lắng nghe dữ liệu được truyền vào hoặc *tìm kiếm từ (context, instance được lưu ở đâu đó). Tại đây nếu có dữ liệu mới đến thì hàm setState sẽ được gọi để làm mới lại giao diện của builder này.

🎯 Các bạn hãy đi sâu vào code của các thư viện để kiểm nghiệm điều mình đề cập nhá.

Các class có cơ chế lắng nghe như Stream, ChangeNotifier,... hoặc các bạn hãy tìm hiểu về observer design pattern để hiểu sâu hơn nhé.

V. Tổng kết

Qua bài viết này mình mong muốn giới thiệu đến các bạn mới cái nhìn cơ bản về lập trình giao diện nói chung và Flutter nói riêng. Chúc các bạn lập trình hiệu quả nhé.

Nguồn tham khảo:

https://ui.dev/imperative-vs-declarative-programming

https://docs.flutter.dev/development/data-and-backend/state-mgmt/intro

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 207

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

Flutter Animation: Creating medium’s clap animation in flutte Part II

Trong phần 1 mình đã giới thiệu với các bạn cơ bản về Animation trong Flutter. Score Widget Size Animation.

0 0 64

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

Flutter - GetX - Using GetConnect to handle API request (Part 4)

Giới thiệu. Xin chào các bạn, lại là mình với series về GetX và Flutter.

0 0 351

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

StatefulWidget và StatelessWidget trong Flutter

I. Mở đầu. Khi các bạn build một ứng dụng với Flutter thì Widgets là thứ không thể thiếu đúng không ạ. Và 2 loại Widget không thể thiếu đó là StatefullWidget và StatelessWidget.

0 0 143

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

Tìm hiểu về Riverpod - Provider nhưng không hắn :v

Trong Flutter có rất nhiều các quản lý state: Provider, Bloc, GetX, Redux,... khó mà nói cái nào tốt hơn cái nào. Tuy nhiên nếu bạn đã làm quen với Provider thì không ngại để tìm hiểu thêm về Riverpod. Một bản nâng cấp của Provider. Nếu bạn để ý thì cái tên "Riverpod" là các chữ cái của "Provider" đ

0 0 67