Sử dụng MVVM để tableView của bạn trở nên mượt mà hơn

1155

Như các bạn đã biết thì hiển thị một tập hợp các dữ liệu là một trong những task phổ biến nhất trong quá trình xây dựng một ứng dụng. Apple SDK đã cung cấp cho chúng ta 2 công cụ để làm việc này, đó là UITableView và UICollectionView.

Table view và collection view đều được thiết kế để hỗ trợ việc hiển thị dữ liệu mà có thể cuộn được. Tuy nhiên khi khối lượng dữ liệu cần hiển thị là rất lớn thì chúng ta còn cần phải đảm bảo việc mượt mà trong các thao tác vuốt, cuộn nữa. Bài viết này dựa trên kinh nghiệm của riêng tôi với table view và collection view trong việc hiển thị dữ liệu lớn một cách mượt mà.

Đầu tiên chúng ta hãy cùng nhau nhìn lướt qua 2 component trên để nắm được những thành phần cơ bản của chúng. UITableView được tối ưu để hiển thị dữ liệu theo các dòng – row hay còn gọi là cell. Việc hiển thị dữ liệu được thực hiện qua các delegates.

UICollectionView thì linh hoạt hơn, chúng ta có thể tùy chỉnh bố cục, layout cho các thành phần được hiển thị trong đó. Tuy nhiên, để có được sự linh hoạt đó thì chúng ta cũng phải thực hiện nhiều tác vụ chi tiết mà vẫn đảm bảo được performance của ứng dụng.
Ở trong bài viết này, tôi sẽ áp dụng phương pháp cho TableView, và tất nhiên các bạn cũng có thể áp dụng nó cho Collection View

Sự tương tác giữa UITableView và UITableViewCell được mô tả qua những event sau:

Trong tất cả những event trên, Table View sẽ truyền vào một giá trị index (row) tương ứng với từng dòng dữ liệu. Dưới đây là mô tả một vòng đời của một đối tượng UITableViewCell:

Đầu tiên, method  tableView(_:cellForRowAt:) sẽ cần phải thực thi càng nhanh càng tốt. Method này được gọi mỗi lần một cell chuẩn bị được hiển thị, tốc độ thực thi càng nhanh thì tác vụ cuộn hay vuốt sẽ càng trở nên mượt mà.

Để làm được việc này thì chúng ta có thể làm một vài thao tác theo chỉ dẫn của tài liệu Apple như sau:

Sau khi khai báo một cell instance có thể tái sử dụng được (dequeueReusableCell(withIdentifier:for:)), chúng ta cần phải config nó bằng việc gán những giá trị cần thiết cho các property của nó.

Khởi tạo View Model cho đối tượng Cell

Có một cách để tất cả những property mà chúng ta cần hiển thị trở nên dễ dàng truy cập và gán giá trị vào hơn đó là sử dụng mô hình  MVVM. Giả dụ rằng khi chúng ta cần hiển thị một tập hợp những user trong table view thì có thể định nghĩa lớp Model cho user như sau:

Sau đó chúng ta định nghĩa View Model cho User như sau:

Đổ dữ liệu theo cách bất đồng bộ và Cache View Models:

Sau khi chúng ta đã khai báo Model và View Model, hãy dung chúng để đổ dữ liệu cho user qua web service, và tất nhiên chúng ta muốn mang đến trải nghiệm tốt nhất có thể, do đó chúng ta phải lưu ý những thứ sau:

  • Tránh block main thread trong khi đổ dữ liệu.
  • Update table View ngay sau khi nhận dữ liệu về.

Điều này có nghĩa rằng chúng ta sẽ đổ dữ liệu một theo hướng bất đồng bộ. Task này sẽ được thực thi qua một controller riêng biệt để tách những logic của việc đổ dữ liệu ra khỏi Model và ViewModel :

Bây giờ chúng ta có thể nhận dữ liệu và update tableView theo hướng bất đồng bộ như sau:

Chúng ta có thể dùng đoạn mã trên để truyền dữ liệu theo nhiều cách khác nhau:

  • Đặt vào viewDidLoad(). khi chúng ta load table view một lần duy nhất.
  • Đặt vào viewWillAppear(_:). khi tableView cần phải load nhiều lần.
  • Còn lại tùy theo yêu cầu của người dùng, chúng ta có thể đặt khối lệnh này ở trong method thực thi yêu cầu đó. Ví dụ như kéo xuống để refesh..vv

Load ảnh bất đồng bộ và lưu lại cache

Việc load và hiển thị ảnh ở trong cell là rất phổ biến, và để cho ra một tác vụ mượt mà nhất có thể, chúng ta hiển nhiên không muốn block main thread để tải ảnh. Có một cách để load ảnh bất đồng bộ đó là tạo một lớp wrapper qua URLSession:

Ở đay chúng ta sẽ load từng tấm ảnh tại background thread và chỉ update UI khi mà đã có đủ data cần có. Bên cạnh đó chúng ta cũng có thể sử dụng những thư viện như SDWebImage hay AlamofireImage.

Tham gia ngay để biết thêm về cuộc chiến

Tùy chỉnh Cell

Để tận dụng hoàn toàn những lợi ích từ View Model, chúng ta có thể tùy chỉnh User cell bằng cách subclass nó ( từ UITableViewCell cho TableView và từ UICollectionViewCell cho collection view). Hướng tiếp cận ở đây đó là tạo một outlet cho từng property của Model mà cần được hiển thị và khởi tạo chúng từ View Model:

Sử dụng Opaque Layers và tránh dùng Gradients

Sử dụng layer trong suốt hay kiểu Gradients đòi hỏi một khối lượng tính toán lớn, do vậy cũng sẽ ảnh hưởng đến performance. Vì thế nếu có thể, chúng ta nên tránh sử dụng chúng, cũ thể chúng ta có thể dùng màu RGB, ví dụ như UIColor.clear:

Sau khi chỉnh sửa xong, chúng ta tổng hợp tất cả các thứ lại như sau:

 

Tổng kết

Như vậy là qua bài viết trên, chúng ta đã có thể tìm ra một trong những ccách làm tối ưu performance cho tableView, collectionView nói riêng và ứng dụng của chúng ta nói chung. Bạn có thể download ví dụ trên tại đây.

Techtalk via Techmaster

 

CHIA SẺ