Mình đã tìm hiểu và nhận ra là khi có thể tạo các Widget bằng cách sử dụng các Function đơn giản thay vì phân lớp StatelessWidget. Ví dụ chúng ta có thể tạo 1 Function như này:

Widget function({ String title, VoidCallback callback }) {
  return GestureDetector(
    onTap: callback,
    child: // some widget
  );
}

Như vậy đoạn code sẽ ngắn gọn hơn so với việc phải viết một StatelessWidget đầy đủ

class SomeWidget extends StatelessWidget {
  final VoidCallback callback;
  final String title;

  const SomeWidget({Key key, this.callback, this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
      return GestureDetector(
        onTap: callback,
        child: // some widget
      );
  }
}

Câu hỏi đặt ra là:

Có sự khác biệt nào ngoài cú pháp giữa các Function và Class để tạo các widget không? Và nó có phải là một cách tốt để sử dụng
trong việc tối ưu code không?

Có một sự khác biệt quan trọng giữa việc sử dụng các Function thay vì các Class, đó là: Framework không biết các Function, nhưng có thể thấy các Class.

Hãy xem xét Function “widget” sau:

Widget functionWidget({ Widget child}) {
  return Container(child: child);
}

Được sử dụng theo cách này

functionWidget(
  child: functionWidget(),
);

Và nó tương đương với Class:

class ClassWidget extends StatelessWidget {
  final Widget child;

  const ClassWidget({Key key, this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: child,
    );
  }
}

được sử dụng như thế này:

new ClassWidget(
  child: new ClassWidget(),
);

Trên đây là 2 cách đều cùng thực hiện một công việc: Tạo 2 Container, với cái này được lồng vào cái kia. Nhưng ta thấy hơi khác một chút.

Trong trường hợp Function mô hình cây WIdget sẽ trông như thế này

Container
  Container

Trong khi với Class, mô hình Widget sẽ là:

ClassWidget
  Container
    ClassWidget
      Container

Điều này rất quan trọng vì nó thay đổi cách hoạt động của mô hình khi cập nhật các Widget con.

Tại sao điều đó lại quan trọng

Bằng cách sử dụng các Function để chia mô hình Widget của bạn thành nhiều Widget nhỏ, bạn có thể bỏ lỡ một số bug để tối ưu hóa hiệu suất của code.

Có thể bạn sẽ không gặp lỗi khi sử dụng các Function, nhưng bằng cách sử dụng các Class, bạn được đảm bảo sẽ không gặp phải những vấn đề này.


Kết luận

Sự khác như khi sử dụng Class và Function:

1. Classes

  • Giúp tối ưu hóa hiệu suất (const constructor, xây dựng lại chi tiết hơn)
  • Đảm bảo rằng việc chuyển đổi giữa hai bố cục khác nhau sẽ xử lý chính xác tài nguyên (các chức năng có thể sử dụng lại một số trạng thái trước đó)
  • Đảm bảo rằng tính năng hot-reload hoạt động bình thường (việc sử dụng các chức năng có thể làm hỏng tính năn hot-reload đối với showDialogs & các phương thức tương tự)
  • Được tích hợp vào trình kiểm tra widget.
    • Các ClassWidget trong mô hình Widget sẽ được devtool hiển thị, giúp ta hiểu nội dung trong màn hình
    • Chúng ta có thể ghi đè debugFillProperties để in thông số được truyền cho Widget con
  • Thông báo lỗi tốt hơn
    Nếu xảy ra ngoại lệ (như ProviderNotFound), framework sẽ cung cấp cho bạn tên của Widget con hiện đang xây dựng. Nếu bạn chỉ chia mô hình widget của mình trong functions + Builder, lỗi của bạn sẽ không có tên hữu ích
  • Có thể xác định các key
  • có thể sử dụng Context API

3. Functions

  • Có ít code hơn (có thể giải quyết bằng cách sử dụng chức năng code-generation functional_widget )

=> Nhìn chung, việc sử dụng các Function hơn các Class trong việc sử dụng lại các widget được coi là một cách làm không tốt.


Tham khảo và dịch tại: https://stackoverflow.com/questions/53234825/what-is-the-difference-between-functions-and-classes-to-create-reusable-widgets