Through the code comparison, we will explain in detail how to choose between MVC, MVP and MVVM, and explore the Android unit testing. The focus of this article is on how to choose, and there is no detailed explanation of each architectural pattern concept (there are many articles on this topic on the Web, you can search for them).

The outline

  • MVC or MVP or MVVM?
  • Confirm selection: MVP + DataBinding
  • Unit Testing (exploration phase)

purpose

  • Improve development efficiency
  • Easy to test
  • Embrace change
  • Reduce maintenance costs

The Android MVC

Example:

Display task details function, detail View layer through XML to write, request data related code will provide interface in the Model layer, and then through the Activity to View and Model layer connection.

Code:

M:public interface TaskModel {
    void loadTask(String taskId, OnTaskListener listener); } V: taskdetail. XML: the interface layout file, which is described in XML and belongs to the V layer. C & V: TaskDetailActivity: Layer C and layer Vpublic class TaskDetailActivity {
    private void initView(a) {
        taskModel.loadTask(taskId, new OnTaskListener() {
            public void onSuccess(Task task) {
                // Layer V code, but currently coupled to layer CdetailTitle.setText(task.getTitle); }}); }}Copy the code

Conclusion:

  • Write simple and fast, suitable for business with simple logic, or demo procedures.
  • Bloated Activity: XML, as the View layer, has too weak control ability to dynamically change the content of the page. It can only write code in the Activity, causing the Activity to be both Controller layer and View layer.
  • The coupling degree is high, the demand changes greatly, and the subsequent maintenance costs are high.
  • Controller can’t be Junit with Android code.

The MVP of the Android

Example:

The verbose View layer is implemented through XML and Activity. The request data related code provides an interface in the Model layer, and then connects the View to the Model layer through Presenter.

Code:

M:public interface TaskModel { 
    void loadTask(String taskId, OnTaskListener listener); } V: taskdetail. XML: the interface layout file, which is described in XML and belongs to the V layer.public class TaskDetailActivity implements TaskDetailView {
    public void showTask(Task task) {
        detailTitle.setText(task.getTitle);
    }  
}

P:
public class TaskDetailPresenter implements Presenter {
    public void getTask(a) {
        taskModel.loadTask(taskId, new OnTaskListener() {
            public void onSuccess(Task task) {
                // Call back to layer V via interface to update UItaskDetailView.showTask(task); }}); }}Copy the code

Conclusion:

  • Reduced coupling between layers facilitates subsequent requirements changes and reduces maintenance costs.
  • The Presenter layer is separate from the Android code and can be used for Junit testing.
  • Lots of interfaces and classes, callbacks to each other, and bloated code.
  • The Presenter layer interacts with the View layer through interfaces, and interface granularity is difficult to control.

The Android MVVM

Example:

Detail View layer through XML and Activity to complete, request data related code will provide interface in the Model layer, and then through the ViewModel to View and Model layer connection.

Code:

M:public interface TaskModel.void loadTask(String taskId.OnTaskListener listener); V: Taskdetail. XML: the interface layout file is described in XML and binding rules are defined in XML. TaskDetailActivity: The Activity is primarily an initialization and supplementary function. VM: TaskDetailViewModel {public void getTask(a) {
              taskModel.loadTask(taskId, new OnTaskListener() {
                    public void onSuccess(Task task) {
                        // Update the UI with binding techniques to make data independent of the UItaskDeatailViewBinding.setTask(task); }}); }}Copy the code

Conclusion:

  • Like MVP, the main difference is the communication between View and ViewModel/Presenter
  • Compared with MVP, it has the advantage of using DataBinding technology to bind data between VM and V layer to improve development efficiency. Due to the limitations of binding technology, some interface processing of V layer still needs the assistance of Activity.
  • Junit testing is not possible with the VM layer doped with Android code.

To determine the selection of

Based on the above comparison, MVP+DataBinding was selected. This architectural pattern is based on MVP and uses the DataBinding library to display the data and bind the View. It doesn’t follow the strict MVVM or MVP model because it uses both ViewModel and Presenter.

DataBinding

This is why we use DataBinding in my last article, which summarizes why we use DataBinding technology by comparing the code. If you are interested, you can read it. Here is a short summary of the article:

DataBinding is data-driven: Automatically updates the UI as the data changes; Event handling: Directly find the target instance to handle the event of the user’s action. This way we don’t need to deal with the UI or controls, we just need to handle the business logic in Java code, very clear, and leave the rest to the Binding library. This reduces code coupling and makes data independent of the UI, which has a positive impact on future program changes and maintenance.

MVP+DataBinding

Example:

Show task details of functionality, data and event binding compared to the base MVP code.

Code:

// Examples of code for common MVP task details:
public void onCreateView(...). {
    detailTitle = (TextView) root.findViewById(R.id.task_detail_title);
    detailComplete = (CheckBox) root.findViewById(R.id.task_detail_complete);
    detailComplete.setOnCheckedChangeListener(
           (cb, isChecked) -> presenter.completeChanged(task, isChecked)
    );
}
@Override
public void showDescription(String title) {
    detailTitle.setText(title);
}
// XML files omit...

//MVP+DataBinding task details
@Override
public void showTask(Task task) {
    viewDataBinding.setTask(task);
}
// Attributes that can be directly bound to the data model through layout files (XML files)
<TextView
    android:id="@+id/task_detail_title"
    android:text="@{task.title}" />
// Event binding can also be implemented directly in layout files (XML files)
<CheckBox
    android:id="@+id/task_detail_complete"
    android:checked="@{task.completed}"
    android:onCheckedChanged="@{(cb, isChecked) -> presenter.completeChanged(task, isChecked)}" />Copy the code

Conclusion:

  • The DataBinding library improves development efficiency by allowing XML layout files to be used to bind data to UI elements. It is also possible to bind an Action Handler (Presenter) to an event that handles user actions. The data can be observed and set so that it is automatically updated when needed (bidirectional binding).
  • The View and Presenter layers need to be tested to increase the workload.
  • Currently Android Studio doesn’t support Databing very well (error reporting and code generation)

Unit Testing (exploration phase)

Presenter

No Android environment is required, so use Junit for testing

  • JUnit: Unit testing framework for the Java language
  • Mockito: a testing framework for mock objects

View

UI testing using Google suggested Espresso (Android environment dependent)

  • AndroidJUnitRunner: JUnit 4 compatible test runner for Android
  • Espresso: Functional UI testing framework

The problem

In current practice, you may find that you need to write additional methods for testing that are not comfortable. And write two layers of tests, the amount of work becomes larger. There are also coverage and maintenance issues, and we are constantly exploring best practices, which will be shared in a future article.

This article comes from my own programming practice, please help to correct the bad places, I hope to help you choose the appropriate architecture mode. Thanks for reading.