.

Sơ qua về Listview.

Để các bạn hiểu hơn về ý chính của bài viết là ShrinkWrap và Slivers thì chúng ta cùng tìm hiểu qua về Listview, những sai lầm phổ biến về Listview.
Listview là một Widget chứa danh sách các Widget khác, đồng thời nó giúp các Widget con có thể cuộn theo chiều ngang hoặc chiều dọc.

Listview vs Listview.builder

.

ListView

Ưu điểm: Linh hoạt đối với số lượng Widget con ít, các Widget con có nhiều type khác nhau (Container, Textfield, Image, Button,…)

Nhược điểm: Render tất cả item trong danh sách widget con, không có cơ chế cache những item con bị ẩn, không được nhìn thấy trên màn hình.

This constructor is appropriate for list views with a small number of children because constructing the List requires doing work for every child that could possibly be displayed in the list view instead of just those children that are actually visible.
https://api.flutter.dev/flutter/widgets/ListView/ListView.html

ListView.builder

Ưu điểm: Tối ưu tài nguyên cho hệ thống tốt, chỉ build và render những item được nhìn thấy trên màn hình. Cuộn tới đâu render tới đó, không render một cục như Listview

Nhược điểm: Chỉ được dùng trong trường hợp các danh sách con cùng loại.

This constructor is appropriate for list views with a large (or infinite) number of children because the builder is called only for those children that are actually visible.
https://api.flutter.dev/flutter/widgets/ListView/ListView.builder.html

ListViews in ListView

Trong thực tế chúng ta thường gặp trường hợp phải lồng các listview vào nhau. Giải pháp của chúng ta là set shrinkWrap: truephysics: const NeverScrollableScrollPhysics() cho các Listview con. Việc này có thể giúp chúng ta giải quyết vấn đề nhưng vô hình chung chúng ta đã phá vỡ cơ chế tối ưu của Listview.builder, đó là chúng chỉ render những item được nhìn thấy trên màn hình.

Mình chứng cho việc này, chúng ta cùng xem ví dụ sau:
https://dartpad.dev/?id=d3e4dfbb688560be3b22baa941e176a6
Hãy run đoạn code ví dụ kết hợp scroll và xem log để thấy tôi nói có đúng không nhé ae. Vừa run code, tất cả các item trong Listview con đều được build, thật là kinh khủng và không chấp nhận được đối với một developer.

Trong thực tế, đặc biệt là chúng ta có một Listview con trong 1 listview chứ số lượng lớn các item, sẽ gây nên tình trạng tốn tài nguyên, giật lag nếu chiếm quá nhiều ram. Điều này thật tệ và không chấp nhận được đối với một sản phẩm. Vậy thì giải pháp là gì, chúng ta cùng đi tìm hiểu tiếp nhé

Slivers + CustomScrollView

solution

Thật may, team Flutter đã tạo ra cho chúng ta một giải pháp, đó là sử dụng Slivers kết hợp với CustomScollView.
Hãy cùng xem qua ví dụ, scroll + xem log để cảm nhận và thầm cảm ơn team Flutter nhé :D.
https://dartpad.dev/?id=ae50a3adb0dac1c9138308a3b12930d3
Ae chạy code và xem log rồi thì chắc tôi cũng không cần giải thích dài dòng nữa đúng không. Đại loại bộ đôi này sẽ giải quyết cho ae bài toàn có 2 danh sách cuộn lồng nhau.

Vậy thì sẽ có ae thắc mắc trong thực tế có khi nào xảy ra tình huống này hay không. Câu trả lời là có, hãy ví dụ trang chủ của một app thương mại điện tử, từ trên xuống là một danh sách các banner quảng cáo, header, danh sách sản phẩm cuộn ngang… và dưới cùng là một danh sách sản phẩm dài vô tận, lướt muốn bở hơi tai. Khi user cuộn càng ngày càng nhiều sản phẩm, nếu không có cơ chế giải phóng bộ nhớ cho danh sách các item đó thì ram càng ngày càng bị đầy và tất nhiên app sẽ càng bị giật lag.

Kết bài

.

Như vậy qua bài viết này có thể giúp anh em tự tin khi đối mặt với các tình huống tương tự. Anh em có ý kiến hay đóng góp gì cho tác giả vui lòng cmt phía dưới nhé. Chúc ae coding vui vẻ hehe.