Android MVP mode and android MVP Mode

Source: Internet
Author: User

Android MVP mode and android MVP Mode
MVP Introduction

I believe everyone is familiar with MVC: M-Model, V-View, C-Controller, and MVP as the evolved version of MVC, the meaning of similar MVPs: M-Model, V-View, and P-Presenter- er. From the perspective of the combination of MVC and MVP, Controlller/Presenter both play the role of logical control and processing in MVC/MVP, and play the role of controlling various business processes. The most different between MVPs and MVC is that M and V are not directly associated, and there is no direct relationship between Model and View. The two are separated by the Presenter layer, it is responsible for controlling the indirect interaction between views and models. The MVP structure is shown below. You can understand this diagram without having to limit it to the following rules, after all, there may be some discrepancies in different scenarios. In Android, the most important thing is that the UI operations basically need to be performed asynchronously, that is, in MainThread, to operate the UI. Therefore, it is reasonable to disconnect the View and Model. In addition, the interaction between Presenter and View and Model can be further achieved through the interface definition interaction operation, or through the interface for more convenient unit testing.

MVP Architecture

There has never been a unified implementation method for the MVP mode of android. Different people have different implementation methods due to their different understandings, in fact, it is difficult to say which one is better and which one is worse. For different occasions, different implementation methods have their own advantages and disadvantages.

The mvp I use is an MVP implementation method proposed by Google. I personally think this method is simple and more suitable for android projects. In traditional MVPs, Model plays a role in processing specific logic, and Presenter plays a role in isolation and decoupling. In Google MVP, Model is weakened, and Model logic is implemented by Presenter, spManager and dbManager can be viewed as models, and View changes are implemented by Fragment. Activity, as a global Controller, is responsible for creating view and presenter instances and connecting them.

Implementation step 1. BasePresenter
public interface BasePresenter {    void start();}
2. BaseView
public interface BaseView<P extends BasePresenter> {    void setPresenter(P presenter);}

The two interfaces are used as the base classes of Presenter and View respectively. Only the most basic methods are defined. The view and presenter on the specific page define the inherited interfaces and add the methods on their own pages.

3. Contract

This is one of the differences between Google MVP and other implementation methods. The contract class is used to define the view and presenter interfaces of the same interface, and naming or commenting through standard methods, you can clearly view the logic of the entire page.

Public interface SampleContract {interface Presenter extends BasePresenter {// obtain the data void getData (App app, int userId); // check whether the data is valid void checkData (); // Delete the message void deleteMsg (App app, int msgId );...} interface View extends BaseView <Presenter> {// display void showLoading () in loading; // refresh the void refreshUI (MessageListEntity. categoryData data); // display the error page void showError ();...}}
4. Specific Impl class

Fragment implements the View interface. Here we use the method newInstance () recommended by Google to create Fragment instances and pass in the required parameters of fragment.

public class SampleFragment extends BaseFragment implements SampleContract.View{    private static final String ARG_PARAM1 = "param1";    private static final String ARG_PARAM2 = "param2";        private String mParam1;    private String mParam2;    private SampleContract.Presenter mPresenter;        /**     * Use this factory method to create a new instance of     * this fragment using the provided parameters.     *     * @param param1 Parameter 1.     * @param param2 Parameter 2.     * @return A new instance of fragment SampleFragment.     */    // TODO: Rename and change types and number of parameters    public static SampleFragment newInstance(String param1, String param2) {        SampleFragment fragment = new SampleFragment();        Bundle args = new Bundle();        args.putString(ARG_PARAM1, param1);        args.putString(ARG_PARAM2, param2);        fragment.setArguments(args);        return fragment;    }    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        if (getArguments() != null) {            mParam1 = getArguments().getString(ARG_PARAM1);            mParam2 = getArguments().getString(ARG_PARAM2);        }    }    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container,                             Bundle savedInstanceState) {        TextView textView = new TextView(getActivity());        textView.setText(R.string.hello_blank_fragment);        return textView;    }    @Override    public void setPresenter(SampleContract.Presenter presenter) {        mPresenter = presenter;    }    @Override    public void refreshUI(MessageListEntity.CategoryData data) {        //change UI    }    @Override    public void showError() {        //change UI    }}

The Presenter implementation class provides a parameter for the corresponding View constructor, holds the reference of the View, and calls the setPresenter () method of the View so that the View also holds the reference of the Presenter, this facilitates the View to call the Presenter method.

public class SamplePresenterImpl implements SampleContract.Presenter {    private SampleContract.View mView;    public SamplePresenterImpl(SampleContract.View mView) {        this.mView = mView;        mView.setPresenter(this);    }    ...}
5. Finally, Activity

Create view and presenter instances and associate them.

Public class SampleActivity extends BaseActivity {public static final String FRAGMENT_TAG = "fragment_tag"; @ Override protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_layout_detail); init ();} private void init () {// initialize view FragmentManager fragmentManager = getSupportFragmentManager (); SampleFragment fragment = (SampleFragment) fragmentManager. findFragmentByTag (FRAGMENT_TAG); if (fragment = null) {fragment = SampleFragment. newInstance (param1, param2); fragmentManager. beginTransaction (). add (R. id. fl_container, fragment, FRAGMENT_TAG ). commit () ;}// initialize presenter new SamplePresenterImpl (fragment );}}
Is the architecture diagram of the Official Google Demo: todo-mvp Mode

Observe the MVP mode in terms of structure


20160510110516376.png why is MVP used?

At the beginning, the article did not talk about the benefits of MVP, but first introduced how to implement MVP. Here I will analyze it to reflect the benefits of MVP.

1. Decoupling

Undoubtedly, this is the biggest benefit. The above example shows that a page is divided into two parts: View logic and business logic. The references held by the two are the interfaces of the other party. Therefore, you can replace the implementation (large page modification) at will, and modifying the view or presenter logic independently will not affect the other party (small modification ).

2. Clear code

In the previous MVC mode, when the logic of a page is complex enough, there may be thousands of rows of activity. It is very difficult to locate a bug in such a class, sometimes the code you typed looks like other people's code. It takes a lot of time to locate the code with a single click. In the MVP mode, the logic of a page can be intuitively Viewed from the Contract class. Find the method of the corresponding logic and then go to the implementation class to find the problem. The efficiency is different from the Japanese.

3. Flexible

Many MVPs use Activity to implement views. Fragment is used here for flexible consideration. Fragment can be reused or replaced. In the face of changing needs, you can easily deal with it. For example, a page is originally a list, and then two tabs are required to be displayed on this page, and the original list is changed to one. Similar situations may be very common. If you use an Activity, you may need to modify a lot of code in the activity class. If you originally used Fragment and MVP, you only need to add one Fragment, modifying the Activity is more in line with the OOP programming philosophy if you switch the Tab logic without modifying any logic of the first Fragment.

4. Simplified

As mentioned at the beginning, Model plays a role in processing specific logic in traditional MVPs, and Presenter plays the role of isolation and decoupling. In this way, the MVP Presenter looks more like a proxy class, simply preventing the View from directly accessing the Model. Although this decoupling method is more efficient, there are very few modifications to the logic of a page in a project. Only product modifications are required, in most cases, only minor changes such as bug fixes need to be completely decoupled. On the other hand, the view logic and business logic of a page are integrated. Therefore, Google's MVP weakened Model, allowing Presenter to replace the Model in the traditional sense, reducing the class that has increased dramatically due to the use of MVP. This method is added to one activity, one fragment (view), one presenter, and one contract (if there is a traditional Model, there will also be one Model interface and one implementation class ).

Note!

1. Is a piece of logic stored in View or Presenter? In fact, from the definition, we can also know that View only processes the interface logic, and any logical judgment should be implemented in presenter. However, in the actual process, it is easy to see the View processing logic. For example, if a network request returns some data, you need to delete or process the data, the processing process is easy to occur in the View layer. This is a situation that needs to be avoided. All judgments that do not involve the interface should be placed in the presenter layer.

2. Class Name and method name specifications. The contract classes on the page end with contract, and the Implementation classes of the presenter end with PresenterImpl. The methods in the View and Presenter interfaces must be known and known. Comments can be added if the meaning is vague. Standardized naming is helpful for subsequent modification and maintenance by others.

3. subthread callback. After processing the sub-thread task in the Presenter, it usually returns to the main thread and calls the View method to refresh the UI. However, if the activity has been destroyed, in addition, tasks in sub-threads (such as network requests) are not canceled. In this case, a null pointer is easily triggered when calling the View method. you should judge before calling the method. Therefore, we recommend that you add an isActive () parameter to view () method to Determine whether the current view is visible:

public interface BaseView<P extends BasePresenter> {    void setPresenter(P presenter);    boolean isActive();}

In fragment, you only need to implement it like this:

    @Override    public boolean isActive() {        return isAdded();    }

In addition, if the Sub-thread task lasts for a long time, or the sub-thread takes too long due to additional factors such as the network, the activity is actually destroy, if the sub-thread of the presenter is still running, it will not be GC, And the presenter holds the fragment (view), resulting in Memory leakage.
To solve this problem, we can solve it through the weak application method. The following is the implementation method:

public abstract class BasePresenterImpl<V extends BaseView> implements BasePresenter {     protected WeakReference<V> mView;     public BasePresenterImpl(V view) {        mView = new WeakReference<V>(view);        view.setPresenter(this);    }     protected boolean isViewActive() {        return mView != null && mView.get().isActive();    }     public void detachView() {        if (mView != null) {            mView.clear();            mView = null;        }    } }

View can also be abstract.



Author: Hu binbing
Link: https://www.jianshu.com/p/bbb3b77d47eb
Source: Simplified book
Copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

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.