An analysis of the official Android MVP architecture _android

Source: Internet
Author: User

Review

For the MVP (Model View presenter) architecture evolved from the famous MVC (Model View Controller) architecture. And the development of Android applications can be seen as an MVC architecture. XML files are typically considered as view roles in MVC in development, while activity is considered the controller role in MVC. But more often than not, activity in actual application development can not act as a controller, but a combination of controller and view. The activity is responsible for both the display of the view and the handling of the business logic. This allows the code to reach thousands of lines in the activity, and even thousands of lines are not enough, and the activity is bloated. So it's not very appropriate for the MVC architecture to be used in Android development. Here's an introduction to the MVP architecture and a look at Google's official example of the MVP architecture.

Introduction to the MVP architecture

For an application we need to abstract each level of it, and in the MVP architecture it will be the UI interface and data isolation, so our application is divided into three levels.

    • View: For the views layer is also the viewing layer, which is only responsible for displaying the data in the view layer, providing a friendly interface to interact with the user. Activity or fragment is often used as the view layer in Android development.
    • Model: For the model layer is also the data layer. It differs from model in the MVC architecture, where it is not just a data model. Model in the MVP architecture it is responsible for data access operations, such as the database read and write, network data requests.
    • Presenter: For the presenter layer he is a bridge between the view layer and the model layer and handles the business logic. Model and view cannot interact directly in the MVP architecture. Therefore, in the presenter layer it will obtain the required data from the model layer, do some proper processing and then submit to the view layer for display. In this way, the view is isolated from model by presenter, so that there is no coupling between view and model, and the business logic is drawn from view.

The MVP chart below looks at the relationships between the various levels of the MVP.

In the MVP architecture, these three layers are abstracted separately into their respective interfaces. The layers are isolated through interfaces, and presenter dependencies on view and model depend on their interfaces. This conforms to the principle of interface isolation, and it is interface-oriented programming. The presenter layer contains a view interface and relies on the model interface to associate the model layer with the view layer. For the view layer, a Presenter member variable is held and only calls to the presenter interface are retained, and the specific business logic is all handled in the presenter interface implementation class.

Official MVP Architecture Analysis

Project Introduction

There is some understanding of the MVP architecture, and in the front-end time Google gives some implementation of the app development architecture.

The project address is: Https://github.com/googlesamples/android-architecture.

Let's go into the readme here and look at this. Google gives you the implementation of the Android development architecture.

The implementation of the above five development architectures represents the completed project so far, while the following two represents the projects in progress. Let's begin by introducing these architectures.

    • TODO-MVP: the base MVP architecture.
    • Todo-mvp-loaders: Based on the MVP architecture, the loaders architecture is used in the acquisition of data.
    • Todo-mvp-databinding: Based on the MVP architecture implementation, the data binding component is adopted.
    • Todo-mvp-clean: The implementation of the clean architecture based on the MVP architecture.
    • Todo-mvp-dagger2: Based on the MVP architecture, a dependency injection dagger2 was used.
    • Dev-todo-mvp-contentproviders: Based on mvp-loaders architecture, Contenpproviders was used.
    • Dev-todo-mvp-rxjava: Based on the MVP architecture, the abstraction of the concurrent processing of the program and the data layer (model in the MVP).

As can be seen from the above introduction, the implementation of all the architecture given by the official is ultimately based on the MVP architecture. So here's an analysis of the MVP architecture TODO-MVP above.

Analysis of the structure of the project

For this project, it implements the function of a memo. Add the unfinished tasks in the work to the to-do list. We can mark the completed tasks in the list, be able to go to the Task Detail page to modify the task content, and also be able to make statistics on the completed tasks and the number of unfinished tasks.

First, let's look at the project structure of TODO-MVP overall

As can be seen from the above illustration, the project contains an app src directory, four test directories in its entirety. The way the code is organized in the SRC directory is divided by function. There are four features included in this project, namely: Task add edit (addedittask), Task completion statistics (statistics), Task Details (taskdetail), Task List display (tasks). For the data packet it is the source of the project, the execution of the database read and write, the network request operations are stored in the package, but also the MVP Architecture model layer. The util package below is the tool class that is used to store some projects. Two interfaces Basepresenter and Baseview are stored at the outermost layer. They are the base class for the presenter layer interface and the view layer interface, and all presenter interfaces and view layer interfaces in the project are inherited from both interfaces.

Now enter the function module to see how the class is divided within the module. The classes are divided into xxactivity,xxfragment,xxpresenter,xxcontract under each functional module. It is also these classes that form the presenter layer and the view layer in the project. Here's how to implement the MVP architecture in this project.

The implementation of the MVP architecture

Here only from the macro focus on the implementation of the MVP architecture, the internal details of the code is not in the specific analysis. Let's add and edit the task to see how the official Android system is implementing the MVP architecture.

Implementation of Model layer

First of all, we start with the most inner layer of the MVP architecture, which is the corresponding model layer. The contents of the corresponding data package in this project. The encapsulation of some data sources, such as databases, under data. The Tasksdatasource interface is provided for the presenter layer. Look at this Tasksdatasource interface here.

Public interface Tasksdatasource {

  interface loadtaskscallback {

    void ontasksloaded (list<task> tasks);

    void Ondatanotavailable ();
  }

  Interface Gettaskcallback {

    void ontaskloaded (Task Task);

    void Ondatanotavailable ();
  }

  void Gettasks (@NonNull loadtaskscallback callback);

  void Gettask (@NonNull String taskId, @NonNull Gettaskcallback callback);

  void Savetask (@NonNull task Task);

  ......
}

The realization of the Tasksdatasource interface is Taskslocaldatasource, and the method in Tasksdatasource is the operation of checking and deleting the database. In Tasksdatasource, the two internal interfaces Loadtaskscallback and Gettaskcallback are the callback interfaces of the model layer. Their real implementation is in the presenter layer. The data is passed to the presenter layer when the data is successfully fetched or passed through the callback interface. Similarly, if a failure is obtained, the presenter layer is also notified by the callback interface. Here's a look at the implementation class for Tasksdatasource.

 public class Taskslocaldatasource implements Tasksdatasource {.... @Override

    public void Gettask (@NonNull String taskId, @NonNull Gettaskcallback callback) {//According to taskId search for the corresponding task ...
    if (task!= null) {callback.ontaskloaded (Task);
    else {callback.ondatanotavailable ();
    @Override public void Savetask (@NonNull task Task) {checknotnull (Task);

    Sqlitedatabase db = Mdbhelper.getwritabledatabase ();
    Contentvalues values = new Contentvalues ();
    Values.put (taskentry.column_name_entry_id, Task.getid ());
    Values.put (Taskentry.column_name_title, Task.gettitle ());
    Values.put (Taskentry.column_name_description, Task.getdescription ());

    Values.put (taskentry.column_name_completed, task.iscompleted ());

    Db.insert (taskentry.table_name, null, values);
  Db.close ();
}

  ......
} 

Here we have the ability to add and edit tasks, so we omit a lot of code. You can see the Gettask method implemented in Taskslocaldatasource, in which the Gettaskcallback callback interface within the Tasksdatasource is passed in. The implementation of the Gettask method can see that the callback method is invoked after querying to a task, and if the two callback methods are implemented in the presenter layer, the data is passed to the presenter layer. When a query to a task is empty, the corresponding action is performed by the callback method.

The same is true for data obtained through network requests, where data can be passed to the presenter layer through a callback method for a successful request, and the corresponding operation can be performed by a callback method for a network request failure.

Interface provided by presenter and view layer

Since the interfaces provided in the presenter and view layers are in a class, it is here to see what interfaces they provide externally. First look at the two base class interface Basepresenter and Baseview.

Basepresenter

Package Com.example.android.architecture.blueprints.todoapp;

Public interface Basepresenter {

  void start ();

}

Only one start method exists in the Basepresenter. This method generally performs the task of fetching data from the model layer in presenter and calling the View interface display. This method is typically invoked in the Onresume method in fragment.

Baseview

Package Com.example.android.architecture.blueprints.todoapp;

Public interface baseview<t> {

  void Setpresenter (T presenter);

}

There is only one Setpresenter method in Baseview, and there is a presenter object for the view layer. And Setpresenter is the initialization of the presenter in view.

Addedittaskcontract

The form of the presenter interface and view interface is different from what we normally see on the Web in the MVP architecture given by the Android official. Here the interface of the presenter and view interface are placed inside the Addedittaskcontract class. This allows us to see more clearly what functions are available in the presenter layer and the view layer to facilitate our future maintenance. Here's a look at this addedittaskcontract class.

Public interface Addedittaskcontract {

  interface View extends baseview<presenter> {

    void Showemptytaskerror ();

    void Showtaskslist ();

    void Settitle (String title);

    void SetDescription (String description);

    Boolean isactive ();
  }

  Interface Presenter extends Basepresenter {

    void CreateTask (string title, string description);

    void Updatetask (string title, string description);

    void Populatetask ();
  }


It is clear here that some data display operations are handled in the view layer, while in the presenter layer, tasks are saved, updated, and so on.

The realization of presenter layer

Let's take a look at how the presenter is implemented.

public class Addedittaskpresenter implements Addedittaskcontract.presenter, Tasksdatasource.gettaskcallback {....

  .. Public Addedittaskpresenter (@Nullable String taskId, @NonNull tasksdatasource tasksrepository, @NonNull ADDEDITTASKC Ontract.
    View addtaskview) {mtaskid = TaskId;
    Mtasksrepository = Checknotnull (tasksrepository);

    Maddtaskview = Checknotnull (Addtaskview);
  Maddtaskview.setpresenter (this);
    @Override public void Start () {if (Mtaskid!= null) {populatetask ()); } ... @Override public void Populatetask () {if (Mtaskid = = null) {throw new RuntimeException ("p
    Opulatetask () was called but the task is new. ");}
  Mtasksrepository.gettask (Mtaskid, this);  @Override public void ontaskloaded (Task Task) {//The view could able to handle UI updates anymore if (Maddtaskview.isactive ())
      {Maddtaskview.settitle (Task.gettitle ()); Maddtaskview.setdescription (Task.getdescriptiOn ());

 }
  }
  ......
}

It can be seen that in addedittaskpresenter it not only implements its own presenter interface, but also implements the Gettaskcallback callback interface. In presenter, the object mtasksrepository of the model layer Tasksdatasource and the object Maddtaskview of the view layer Addedittaskcontract.view are included. So the whole business logic is handled in the presenter.

From the presenter business processing can be seen, first call the model layer interface Gettask method, through the TaskID to query task. After querying to a task, a callback interface gettaskcallback for the model layer is implemented in the presenter layer. At this time, the Task object is acquired through the Ontaskloaded method in the presenter layer, and the display of the data is realized by invoking the view layer interface.

Implementation of the View layer

The implementation of the view is in fragment, and in the activity is the addition of fragment, presenter creation. Here's a look at the Addedittaskactivity class first.

public class Addedittaskactivity extends Appcompatactivity {

  @Override
  protected void OnCreate (Bundle Savedinstancestate) {
    super.oncreate (savedinstancestate);
    Setcontentview (r.layout.addtask_act);

    ......

    if (addedittaskfragment = = null) {
      addedittaskfragment = addedittaskfragment.newinstance ();
      ......
      Activityutils.addfragmenttoactivity (Getsupportfragmentmanager (),
          addedittaskfragment, R.id.contentFrame);
    }

    //Create the presenter
    new Addedittaskpresenter (
        taskId,
        injection.providetasksrepository ( Getapplicationcontext ()),
        addedittaskfragment);

  ......
}

The functionality provided by the activity is also very simple, first creating the fragment object and adding it to the activity. The presenter object is then created and the fragment is passed to the presenter.

Let's take a look at the realization of view, which is fragment.

public class Addedittaskfragment extends Fragment implements Addedittaskcontract.view {

  ...

  @Override public
  void Onresume () {
    super.onresume ();
    Mpresenter.start ();
  }

  @Override public
  void Setpresenter (@NonNull Addedittaskcontract.presenter presenter) {
    Mpresenter = Checknotnull (presenter);
  }

  ......

  @Override public
  void Settitle (String title) {
    Mtitle.settext (title);
  }

  ......
}

In this for the source code is not too much posted. In fragment, the presenter object is obtained by Setpresenter. And by calling the method in presenter to achieve business processing. In fragment, however, there are only a few actions on the UI. This reduces the number of fragment types of code and makes the logic clearer.

We notice that the implementation of the view layer is accomplished through fragment. Why do you use fragment rather than activity for the view implementation? Take a look at how the authorities explain it.

The separation between activity and Fragment fits nicely with this implementation of mvp:the activity is the overall cont Roller that creates and connects the views and presenters.

The Tablet layout or screens with multiple views take advantage the fragments framework.

There are two explanations for why the fragment are used.

    • Separation through activity and fragment is ideal for the implementation of the MVP architecture. This is where the activity as a global controller is linked to the presenter view.
    • Using fragment is more advantageous to the layout of a tablet computer or a multiple view screen.

Summarize

The use of MVP architecture shows that the responsibilities between the various levels are more single and clear, but also to a large extent reduce the coupling of the code. For the official MVP architecture example, Google has also made it clear that the examples of these architectures they give are just a reference, not a standard. So there is a greater scope for the base MVP architecture. For example, a comprehensive Google-given example. We can build a clean architecture by using Dagger2,rxjava, based on the MVP architecture. is also a good choice.

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.