Tìm hiểu các mô hình Kiến trúc trong phát triển ứng dụng trong android.

Chào mọi người. Lần trước mình đã có đăng một bài tìm hiểu DataBinding trong Android. Để ứng dụng nó vào trong việc phát triển phần mềm thì chúng ta có thể ứng dụng nó với các framework như MVC , MVP , MVVM. Ở bài này mình sẽ giới thiệu về các mô hình kiến trúc trên để ứng dụng vào trong việc phát triển ứng dụng Android.

1. Giới thiệu

A. Model View Controller (MVC Parttern)

MVC design parttern chia một đối tượng đồ họa (UI Component) bao gồm 3 thành phần cơ bản: Model, View, và Controller. Model có trách nhiệm đối với toàn bộ dữ liệu cũng như trạng thái của đối tượng đồ họa. View chính là thể hiện trực quan của Model, hay nói cách khác chính là giao diện của đối tượng đồ họa. Và Controller điều khiển việc tương tác giữa đối tượng đồ họa với người sử dụng cũng như những đối tượng khác. mvc.png.

  • ####Model : Model đại diện cho một nhóm các lớp mô tả tầng các quy tắc xử lý dữ liệu. Ví dụ Bussines Model có thể mô tả các hoạt động truy vấn dữ liệu từ cơ sở dữ liệu thì được gọi là Data Model. Cũng như định nghĩa ra các quy tắc tương tác với dữ liệu như dữ liệu có thể thay đổi hoặc thao tác vào dữ liệu.
  • ####View : View đại diện cho các thành phần giao diện người dùng (UI components). Nó chỉ có trách nhiệm hiển thị dữ liệu nhận được từ controller như là một kết quả. Cũng có thể làm thay đổi model vào trong UI.
  • ####Controller : Controller đại diện cho tầng xử lý dữ liệu được yêu cầu nhận được. Nhận đầu vào từ người dùng thông qua các View. Sau đó xử lý dữ liệu của người dùng và trả kết quả lại cho View. Thông thường, nó đóng vai trò là điều phối viên giữa View và Model.

B. Model View Presenter (MVP Parttern)

MVP parttern tương tự như MVC parttern. Tầng Controller của MVC được thay thế bởi tầng Presenter. Mẫu parttern này được chia thành 3 tầng : Model, View, Presenter mvp.png

  • ####Model : Cũng giống với Model của MVC Parttern.

  • ####View : View đại diện cho các thành phần giao diện người dùng (UI components). Nó chỉ có trách nhiệm hiển thị dữ liệu nhận được từ presenter như là một kết quả. Cũng có thể làm thay đổi model vào trong UI.

  • ####Presenter : Presenter có nhiệm vụ xử lý tất cả các sự kiện UI thay cho View. Điều này có nghĩ khi nhận đầu vào từ người dùng thông qua các View. Sau đó xử lý dữ liệu của người dùng thông qua Model và trả kết quả lại cho View. Không giống như View và Controller. Presenter và View hoàn toàn tách rời nhau và giao tiếp với nhau thông qua một Interface.

  • Các điểm quan trọng cần biết của Mô hình MVP.

    • Người dùng tương tác với các view.
    • Có quan hệ một-một giữa View và Presenter nghĩa là Một View chỉ ánh xạ tới một Presenter duy nhất.
    • View tham chiếu đến Presenter và không tham chiếu đến Model.

C. Model View ViewModel (MVVM)

MVVM hỗ trợ kiểu Two-way Databinding giữa View và Model. Việc này cho phép việc tự động cập nhật các thay đổi hay trạng thái từ ViewModel đến View. Thông thường ViewModel sử dụng Observer Pattern để notify các thay đổi trong ViewModel đến Model. MVVM.png

  • ####Model : Cũng giống với Model của MVC Parttern.

  • ####View : View đại diện cho các thành phần giao diện người dùng (UI components). Nó chỉ có trách nhiệm hiển thị dữ liệu nhận được từ presenter như là một kết quả. Cũng có thể làm thay đổi model vào trong UI.

  • ####View Model : ViewModel phụ trách cho các Expose Method, các Command và các thuộc tính khác giúp lưu trữ trạng thái của View. Khi thao tác dữ liệu trong model thì như là một kết quả của hành động nào đó của View và kích hoạt sự kiện trong chính View đó.

  • Các điểm quan trọng cần biết của Mô hình MVP.

    • Người dùng tương tác với các view.
    • Có quan hệ nhiều-một giữa View và ViewModel nghĩa là Nhiều View chỉ ánh xạ tới một VideoModel duy nhất.
    • View tham chiếu đến ViewModel và ViewModel không nắm giữ thông tin gì của View
    • Hỗ trợ two-way databinding giữa View và ViewModel.

2. Implement các kiến trúc mô hình trên vào trong phát triển ứng dụng

Bắt đầu từ mục này mình sẽ dùng từ khóa Controller để gọi chung Controller , Presenter , ViewModel và các thành phần đều được sử dụng giống như 3 cái trên .Mình thấy cách tiếp cận đơn giản là sử dụng Activity làm ControllerFragment làm "View". Nhưng việc này nó làm giảm sự linh hoạt và khả năng tái sử dụng của code. android_implement.png.

A. Lớp UI (Ví dụ LinearLayout) dành cho tầng View

Tầng View nên kế thừa từ các android view (UI elements) giống như LinearLayout hay ViewGroup. Các tầng UI nên sử dụng lại các hàm đã có của lớp cha. Không có phụ thuộc gì vào tầng Controller.

class MyView.java của mình sẽ viết mẫu như thế này :

@override
public void registerController(MyController controller) {
    this.controller = controller;
    controller.setListener(this);
    user = controller.getuser;
    userNameLabel.setText(user.getName);
}

@Override
public void unRegisterController(){
    controller.setListener(null);
    this.controller = null;
}
@Override
protected void onLogIn(User user){
    if (!user.isCustomer) {
        displayPlzBuyDialog();
    }
}

B. Lớp Controller

Các lớp Controller không nên kế thừa từ bất kỳ class nào của Android. Hãy nhớ luôn giữ nó tách biệt khỏi Activity hoặc Fragment để có thể tái sử dụng nó. Khi đặt tay vào tạo ra lớp controller nên nhớ :

  • Nó có vai trò như một dạng Glue-code ở giữa View và Model.Single responsibility.
  • Đẩy các sự kiện đến các lớp controller khác.
  • Tách khỏi các class thuộc android, để có thể tái sử dụng lại.

Class MyController.java sẽ viết dạng mẫu thế này :

protected User getUser(){
    return model.getUser();
}

protected void onClickBuy(){
    analytics.customEvent(new Event(Analytics.SCREEN_NAME, Analytics.ACCOUNT_EVENT, Analytics.NEW_SUBCRIPTION, user.getUUID));
    userWebService.subscribe(type, vat);
}

protected interface Listener {
    void onLogIn(User user);
    analytics.onUserLogin(user);
}

C. Lớp Activity có chứa Controller

Khi tạo ra lớp Activity có chứa Controller và View sẽ có dạng như sau :

MyActivity.java

 MyController controller;
protected void onCreate(){
    MyModel model = new MyModelUserDB(this);
    AnalyticsFacade analytics = MyApp.getAnalyticsFacade(this);
    UserWebService userWebService = new UserWebServiceImp();
    MyView view = findViewById("R.id.myview");
    controller = new MyController(model, userWebService, analytics)
    view.registerController(controller);
}

protected void onDestroy(){
    view.unRegisterController();
}

3. Các Mô hình kiến trúc giúp ích trong việc Testing.

Như ở trên thì mình đã có thể hoàn toàn thực thi được một tính năng mà tách rời khỏi Activity. Việc này làm cho việc testing trở nên dễ dàng hơn.Bình thường Activity phải xử lý rất nhiều thứ (device configuration, navigation, style, action bar). Với Robolectric có thể cung cấp các phương pháp test có thể Mocks tất cả các dependencies và cho phép unit test. Đây là class MyRobolectricTest.java tôi viết mẫu :

@RunWith(RobolectricGradleTestRunner.class)
@Config(application = MockApplication.class)
public class MyFeatureTest {

    @Before
    public void beforeTest() {
        RoboHelper.mockSharedPreferences();
    }

    @Test
    public void viewTest() {
        Context context = Robolectric.getShadowApplication().getApplicationContext();
        MyView view = new MyView(context);
        Mock<MyController> mockController = Mockito.mock(MyController.class);
        view.registerController(mockController);
        view.onLogin(mockUser)
        Robolectric.assertVisible("R.id.login_dialog");
    }

    @Test
    public void controllerTest() {
        Context context = Robolectric.getShadowApplication().getApplicationContext();
        MyController controller = new MyController(mockModel, mockAPI, mockAnalytics);
        assertEqual(mockModel.getUser(), controller.getUser());
    }
}

**3. Các thư viện và framework có sẵn **

Các framework ở bên dưới cho phép thực hiện các mô hình kiến trúc ở trên tôi đã giới thiệu. Hiện tại chúng ta đang tìm hiểu thì chắc chưa cần tới chúng. Nhưng chúng sẽ hữu ích nếu chúng ta mô phỏng chúng và tạo ra một tầng base-code cho riêng mình 😃.

Square mortar : Đây là một thư viện đơn giản. Nó dễ dàng kết nối đến View với Controller. Nó là một Overlay Composable cho Android lifecycle. Nó để hỗ trợ trong việc sử dụng Views như các đơn vị mô-đun của các ứng dụng Android.

inloop AndroidViewModel : Thư viện này làm việc tách biệt dữ liệu và handler trạng thái từ Fragment hoặc Activity mà không cần có nhiều boilerplate-code.

sockeqwe mosby : : Một thư viện Model-View-Presenter cho các ứng dụng Android được phát triển mới .

Nguồn (https://medium.com/android-news/android-architecture-2f12e1c7d4db)