MVP trong Android
Mô hình MVP là gì?
MVP là một mô hình kiến trúc hướng giao diện người dùng, được thiết kế để tạo thuận lợi cho việc kiểm thử đơn vị (unit testing) và tăng tính tách biệt giữa tầng dữ liệu và tầng hiển thị dữ liệu trong mô hình MVC.
Mô hình MVP cho phép tách tầng trình diễn (Presenter) ra khỏi tầng dữ liệu (Model), vì vậy tương tác với giao diện được tách biệt với cách chúng ta biểu diễn nó trên màn hình (View), hay nói cách khác, tất cả logic khi người dùng tương tác được tách ra và đưa vào tầng trình diễn. Thiết kế lý tưởng nhất là với cùng một logic được áp dụng cho nhiều View khác nhau và hoán đổi được cho nhau.
Trong đó:
Model
là một interface xác định cách mà dữ liệu được hiển thị trong giao diện người dùng.View
là một giao diện người dùng thụ động hiển thị dữ liệu (Model
) và tiếp nhận tương tác người dùng và truyền tới đểPresenter
xử lý tương tác.Presenter
được ví như middle-man. Khi người dùng tương tác vớiView
,Presenter
tiếp nhận tương tác người dùng và updateModel
. KhiModel
được update hay có thay đổi,Presenter
lấy dữ liệu từModel
, định dạng và đưa tớiView
để hiển thị.
Luồng dữ liệu trong mô hình MVP
Điểm khác biệt dễ thấy nhất ở đây khi so sánh mô hình MVP với mô hình MVC chính là vị trí cũng như chức năng của tầng Presenter và View so với tầng Controller:
Trong mô hình MVP, tầng View là tầng duy nhất tiếp nhận tương tác người dùng thay vì cả 2 tầng View và tầng Controller trong mô hình MVC. Logic xử lý tương tác cũng như logic xử lý dữ liệu hiển thị được tách ra trong tầng Presenter thay vì được gộp chung với tiếp nhận tương tác trong Controller.
Tại sao sử dụng MVP?
Trong Android, có một vấn đề phát sinh từ thực tế là các cơ chế xử lý tương tác trong Android được kết hợp chặt chẽ giữa giao diện người dùng và xử lý, truy cập dữ liệu.
- Một ví dụ điển hình là
CursorAdapter
, đây là sự kết hợp của việc định dạng dữ liệu với xử lý tương tác giao diện. Đôi khi trong đó còn bao gồm cả xử lý dữ liệu ở mức sâu hơn (như tương tác với CSDL) thông quaCursor
.
Việc kết hợp này có thể giúp giảm thiểu lượng code trong ứng dụng cũng như gộp các xử lý, logic trong ứng dụng vào cùng một nơi. Nhưng đối với một ứng dụng liên tục phát triển, hay một ứng dụng lớn, việc này khiến cho lượng code trên mỗi logic trở nên rất lớn, các logic xen lần, chồng chéo lên nhau, rất khó cho việc đọc hiểu, bảo trì cũng như mở rộng.
Phân tầng, phân lớp ứng dụng có thể giảm đi hiệu năng do ứng dụng cần thêm nhiều tài nguyên, nhưng tính khả chuyển của ứng dụng cũng tăng gấp nhiều lần., không những thế còn mở rộng khả năng cho phép kiểm thử từng phần của ứng dụng trở nên dễ dàng hơn. Chính vì thế cân nhắc giữa hiệu năng và tính dễ dàng mở rộng, bảo trì là hết sức quan trọng.
Trong Android, kiểm thử là một vấn đề khó khăn vì mối liên kết chặt chẽ giữa giao diện, logic và dữ liệu. MVP tách biệt giao diện khỏi dữ liệu, chia ứng dụng ra thành ít nhất ba lớp khác nhau, từ đó có thể kiểm thử một các độc lập. Với MVP ta có thể kiểm thử đo đạc một cách tối đa các logic của ứng dụng.
Triển khai MVP trên Android
Có rất nhiều biến thể cũng như phương pháp triển khai MVP, tất cả mọi người có thể điều chỉnh mô hình này tùy theo nhu cầu và cách họ cảm thấy thoải mái hơn. Các mô hình này, về cơ bản khác nhau ở số lượng chức năng mà tầng Presenter đảm nhận.
Một view nhận tương tách từ người dùng disable hoặc enable progress bar, liệu có nên giao nhiệm vụ này cho một presenter? Một Activity sẽ nhận sự kiện click vào nút settings trên ActionBar hay sự kiện này sẽ được một đối tượng presenter trong Activity đảm nhận?
Những câu hỏi như vậy tạo ra nhiều cách để chúng ta triển khai mô hình MVP, và trên thực tế chưa có một tiêu chuẩn chính xác nào được đưa ra. Vì vậy dưới đây tôi xin trình bày một trong những phương pháp đó.
Tầng trình diễn - Presenter
Tầng trình diễn có trách nhiệm như một middle-man giữa View và Model. Nó lấy dữ liệu từ Model, định dạng và trả về cho View. Nhưng không giống như MVC, nó cũng quyết định những gì sẽ xảy ra khi người dùng tương tác với View, hay nói cách khác nó hàm chứa logic ứng dụng.
Tầng logic dữ liệu - Model
Trong một ứng dụng với thiết kế kiến trúc tốt, mô hình này sẽ chỉ là một gateway giữa tầng domainvà tầng business logic. Trong mô hình Clean Architecture của Uncle Bob, Model sẽ là một interactor thự thi một use case. Để đơn giản, ở đây Model đơn thuần được nhìn nhận như một data source - cung cấp dữ liệu chúng ta muốn hiển thị trong giao diện ứng dụng.
Tầng giao diện - View
View, thường được implement bởi một Activity (hoặc có thể là một Fragment, một View ... tùy thuộc vào cấu trúc ứng dụng), Activity này sẽ chứa một thuộc tính là một lớp Presenter. Lý tưởng nhất Presenter nên được cung cấp bởi một Dependency Injection framewok như Dagger, nhưng trong trường hợp ứng dụng không sử dụng một thư viện hay framework như vậy ta hoàn toàn có thể tạo ra các đối tượng Presenter này.