On MVP and MVVM of Android Architecture

Keywords: Android Fragment xml Google

Reprinted from: http://www.cnblogs.com/BoBoMEe/p/5573447.html

Summary

MVP(Model-View-Presenter) is a variant and evolutionary model of traditional MVC(Model-View-Controller) in Android development. Mainly used to isolate UI, UI logic and business logic, data, create loosely coupled and reusable objects.

We know that View layer is changeable and diverse, and business logic is also diverse. Compared with traditional MVC, P acts as C.
Model stores data, View represents the performance of Model, Presenter coordinates communication between them.

Then there are some variants based on MVP, such as MVVM,MVPVM, etc. Compared with MVP, MVVM makes data binding easier. MVPVM introduces Presenter layer into MVVM.

MVC,MVP,MVVM,MVPVM diagrams

Thank you for your source blog and photo provider.

MVC:

View in MVC accepts events and calls Controller to operate the Model. At the same time, when the data of the Model instance changes, Controller updates the interface (of course, View can also update the Model directly).

In traditional development, Activity acts as both Controller and View. It needs to accept user response operation Model and update the interface.
One advantage of this method is that the update of data becomes simple, but the disadvantage is obvious. Activity is not bloated, and it is not easy to maintain later.

MVP:

In MVP, business logic is separately extracted from Presenter, and the View layer becomes a passive thing. Presenter is responsible for completing the interaction between the View layer and the Model layer.
View can't interact directly with Model (Model and View are allowed to interact in MVC). It will only update when Presenter informs it of the update.
And Presenter and View interact through interfaces.

MVVM:

MVVM corresponds to data binding on Android. MVVM was first used in WPF. Through the mapping of ViewModel and View, the two-way binding of View and Model was completed.
View events are passed directly to the ViewModel, which operates on the Model and receives updates. The event is then fed back to the View.
Because of the coupling between ViewModel and View, MVVM has one disadvantage: the reuse of View.
With Presenter removed, the View layer is still overweight.

MVPVM:

MVPVM is an evolutionary version of MVP and MVVM, which reduces the coupling between ViewModel and View. View only needs to implement the update of the ViewModel's observer interface. ViewModel no longer operates directly on the Model, but is handed over to Presenter.Presenter to operate the Model and feed back to the ViewModel.
Model,View,ViewModel are linked through Presenter.

MVP practice

Google official android-architecture It is undoubtedly the best material for learning MVP. The official project shows how to realize MVP in different ways. It shows that the same function can be achieved through different ways, such as basic,loaders,data binding,clean,dagger,content provider,rxjava. Of course, we only need to grasp the essence of MVP and get to know by analogy.

Experience of Seeing Official MVP

  • Individual module extracts IContract interface to manage IView and Presenter interface, which is clear at a glance and easy to maintain.

    public interface AddEditTaskContract {
    
    interface View extends BaseView<Presenter> {
    //...
    }
    
    interface Presenter extends BasePresenter {
    //...
    }
    }
  • When Fragment acts as View, Activity is responsible for creating instances of IView and Presenter and associating them, as illustrated by the official picture.

Code description:

//todo-mvp$TasksActivity
@Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.tasks_act);
       // ...
       TasksFragment tasksFragment =
               (TasksFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);
       //...
       mTasksPresenter = new TasksPresenter(
               Injection.provideTasksRepository(getApplicationContext()), tasksFragment);
       //...
   }
  • IPresenter is implemented by a specific Presenter, IView is implemented by the View layer (Activity/Fragment), and the IView implementation class contains Presenter, which binds in the following way.

    public interface BaseView<T> {
      // Keep a reference to Presenter in View.
      void setPresenter(T presenter);
    }
  • At the same time, the IView object (used to update View) needs to be passed in when Presenter is constructed.

public class TasksPresenter implements TasksContract.Presenter {
    private final TasksRepository mTasksRepository;
    private final TasksContract.View mTasksView;
//...
    public TasksPresenter(@NonNull TasksRepository tasksRepository, @NonNull TasksContract.View tasksView) {
        mTasksRepository = checkNotNull(tasksRepository, "tasksRepository cannot be null");
        mTasksView = checkNotNull(tasksView, "tasksView cannot be null!");
//setPresenter
        mTasksView.setPresenter(this);
    }
  • Model is not only a JavaBean, but also has business logic to manipulate data (acquisition, storage, update). At the same time, Model can also extract business into interfaces, so that it can expand data sources at will.

MVP variant

The benefits of MVP architecture are not much to say, but using Activity/Fragment as the View layer has the following problems.
Reference resources A New Way of Implementing MVP Model in android

  • When memory is insufficient and Activity is recycled, this makes state preservation and recovery a problem, because it involves Model operations.
  • Life cycle control is also troublesome, requiring a bunch of life cycle-related interface specifications to be written in Presenter

  • Activity contains a lot of system services, which are easy to operate logically.

Use Activity/Fragment as Presenter

System services and business logic in Activity/Fragment are closely related. Ideally, View does not involve logical operations.

Activity/Fragment, as Presenter, needs to be managed by extracting its UI logic into a separate class.

UI logical interface

public interface Vu {
    void inflate(LayoutInflater inflater, ViewGroup container, Bundle bundle);
    View getView();
}

BaseActivity as Presenter covers all lifecycle approaches

public abstract class BasePresenterActivity<V extends Vu> extends Activity {

    protected V vu;

    @Override
    protected final void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        try {
            vu = getVuClass().newInstance();
            vu.inflate(getLayoutInflater(), null,null);
            setContentView(vu.getView());
            onBindVu();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected final void onDestroy() {
        onDestroyVu();
        vu = null;
        super.onDestroy();
    }

    protected abstract Class<V> getVuClass();

    protected void onBindVu(){};

    protected void onDestroyVu() {};

}

For instance:

Specific UI logic, whether Presenter becomes Activity or Fragment, need not be changed. Change View's external operation in the periodic method.

public class HelloVu implements Vu {

View view;
TextView helloView;

@Override
public void init(LayoutInflater inflater, ViewGroup container) {
    view = inflater.inflate(R.layout.hello, container, false);
    helloView = (TextView) view.findViewById(R.id.hello);
}

@Override
public View getView() {
    return view;
}

public void setHelloMessage(String msg){
    helloView.setText(msg);
}

}

Specific Presenter

public class HelloActivity extends BasePresenterActivity {
@Override
protected void onBindVu() {
    vu.setHelloMessage("Hello World!");
}

@Override
protected Class<MainVu> getVuClass() {
    return HelloVu.class;
}

}

MVVM: Dynamic Binding of Data

Official documents:
https://developer.android.com/topic/libraries/data-binding/index.html
With Data Binding, our xml is not the same as before. Copied from official documents

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable name="user" type="com.example.User"/>
    </data>
    <LinearLayout>
    ....
    </LinearLayout>
</layout>

The setContentView of the corresponding Activity will also change

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
   User user = new User("Test", "User");
   binding.setUser(user);
}

Here a JavaBean corresponds to an xml layout file, and the reuse of View becomes very difficult.

The MVP: The Combination of MVVM and MVP

TheMVP solves this problem by defining the ViewModel interface in Presenter to realize the combination of bidirectional data binding and MVP.
Project address: kymjs/TheMVP

Core code: The IDelegate here is comparable to the Vu above

//ViewModel interface
public interface DataBinder<T extends IDelegate, D extends IModel> {
    /**
     * Bind data to View so that when the data changes, the framework knows which View the data is bound to and automatically changes the ui.
     * This method is called back when the data changes.
     *
     * @param viewDelegate View Layer Agent
     * @param data         Data Model Objects
     */
    void viewBindModel(T viewDelegate, D data);
}

Presenter: Call notifyModelChanged() to update View when data changes

public abstract class DataBindActivity<T extends IDelegate> extends
        ActivityPresenter<T> {
    protected DataBinder binder;

    public abstract DataBinder getDataBinder();

    public <D extends IModel> void notifyModelChanged(D data) {
        binder.viewBindModel(viewDelegate, data);
    }
}

MVPVM:View Multiplexing and Slimming

In the introduction of the author of MVVPVM.

  • The Model layer, similar to the Model in MVP, is PO or DO.
  • View layer is still acted by Activity/Fragment, but it needs to implement the observer interface of ViewModel to update View dynamically.
  • The Presenter layer, as shown in the figure above, serves as the core and connects M, V, and VM.
  • VM layer is similar to VM in MVVM, just to make VM reusable. It is no longer bound to a specific View, and no longer operates directly on Model.

See: Starting from scratch, the new Android project 3 - MVPVM in Action, who told you that MVP and MVVM are mutually exclusive

Reference resources:

A New Way of Implementing MVP Model in android

ANDROID MVP Model: A Simple and Easy Introduction

MVVM_Android-CleanArchitecture

Starting from scratch, the new Android project 3 - MVPVM in Action, who told you that MVP and MVVM are mutually exclusive

Developing Android Application with MVP Architecture

Posted by noon on Wed, 10 Apr 2019 12:51:31 -0700