Android architecture --MVP little understanding of architecture

1. Frame acquaintance

First frame before speaking, ask yourself the question, why use the framework? Use the framework to give their developers What are the benefits ?

At this writing the code, you will find more and more with the code, the code more difficult to sort out the logic and think less Activity as much as possible. With time and the increase of iterations, the function will also be altered, this time without a good architecture, in an iterative process program will be damaged, expand the work extremely difficult.

What MVP framework is ?
At this writing the code, to avoid creating god classes . That Avoid creating omniscient, omnipotent God class. If a class takes time from other classes through the Get () and Set () to retrieve the data (that is, require in-depth business and tell them how to do it), whether or not we should treat these functions to other functions to better organize the class God rather than class. Activity is God like , with the amount of code Activity increased over time, it will eventually become a collection of components that can not be reused. God kind of high maintenance costs, it is difficult to understand the ongoing operation, and it is difficult to test and expand.

Activity at the same time there is business logic and UI logic , not only caused Activity bloated, and results in data binding and other operations become complicated, so we must first solve a problem is the separation of concerns, and MVP architecture is the prime example.

MVP pattern business logic and UI logic Activity in separated , so that only the processing Activity UI logic, other business logic layer processing by the Presenter, which brings the following advantages:

  • Isolated view and business logic, reducing the coupling
  • Activity only processing tasks lifecycle, code becomes simple
  • View logic and business logic are abstracted to the View and Presenter interface, increasing code readability
  • Presenter is abstracted into the interface, there may be a variety of specific implementations, it is convenient unit testing
  • Presenter business logic pumped in to avoid references to a background thread leads Activity Activity resource recovery system can not be causing memory
    leaks and OOM.

1.1 MVP concept

MVP representatives Model, ViewandPresenter

  • View layer: responsible for handling user events and view part of the show, which displays local data . After obtaining the data, transfer the data to the view layer and the display data. At the same time the click event view layers such as processing occurs here, too, the real data processing in the model layer processing. In Android, or it may be Fragment Activity class .

  • Model layer:
    responsible for accessing data, process the data that is simple, does not take over other tasks. Data may be remote Server API, SharedPreference local database or the like.

  • Presenter layer:
    connecting a bridge (or adapted) Model and the View. After obtaining the data to the M layer layer P, P layer and then to the View layer. Similarly, the process click View events P layer by layer to inform the M layers for additional data processing.

In the MVP, View, and Presenter are one- of (the MVVM-many)

MVP separation of view and model layer, Presenter layer acted as a bridge, View layer is only responsible for updating the interface can be, View where we need to understand just a viewinterface, it is the view of the interface, so we are doing unit tests when you can Presenter very easy to write the code layer

Here Insert Picture Description

Calling sequence between three to view-> presenter-> model can not reverse call! Not cross-level call!
How to model layer back to the Presenter layer? How Presenter View control layer? As shown below
Here Insert Picture Description
the bottom layer do not directly to the feedback, but through View, Callback feedback is made higher, this would resolve the asynchronous data updating operation request interface. FIG View and are in the form Callback interface.

Activity View defined in the specific operation, mainly the request data updates in the interface class

Callback request data is defined in a variety of state feedback: success, failure, abnormal

MVP preliminary schema directory map
The figure is a common directory structure built my brief MVP mode, in which:

  • base : Base class for the app store
  • common: Storage abnormal constants, interfaces, common things
  • bean: Used to store the data defined
  • contract: A contract packet connection layer and the P layer V
  • parserStore some json parsing strings such as:
  • presenter: P layer, and the layer is responsible for connecting V M layer, center manager.
  • ui: This package is stored below the main part of it with UI-related
    • activity: Store Activity class
    • fragment: Storage Fragment class
    • adapter: Adapter class
  • utils: Storage tools
  • widget: Some components contain custom of

2. Poverty version MVP mode

The central idea MVP architecture is oriented programming interface , call level interface object used, the interface to call methods to achieve to achieve layer interface method, and examples of the call level.

Here Insert Picture Description
In the MVP architecture: an interface layer MVP method We must abstract, three simultaneously write interface implementation class (V activity or a fragment layer is typically inherited view layer interface), where V P layer interface object holding layer , P layer and the holding layer V layer interface object M, P M layer provides data layer . MVP is formed between the three architectures, among the three layers are interconnected by P.

Here, we first realize a simple MVP architecture

  • First define an interface, all interfaces in MVP in the interface:
interface View {
        //显示数据
        void showData(String str);

    }

    interface Presenter  {
         //通知model要获取数据并把model返回的数据交给view层
        void getData();

    }

    interface Model {
         //获取数据
       String doData();

    }
  • 创建一个类,实现P接口,这里即P层,P层持有V层和M层接口对象
public class TestPresenter implements TestContract.Presenter {

    private TestContract.Model model;	//持有M层接口对象
    private TestContract.View view;		// 持有V层接口对象

    public TestPresenter (TestContract.Model model, TestContract.View view) {
        this.model = model;
        this.view = view;
    }


    @Override
    public void getData() {
        view.showData(model.doData());
    }

}
  • 创建一个类,实现M接口对象,即M层,M层为P层提供数据
public class TestModel implements TestContract.Model {

    private static TestModel model = new TestModel();

    public static TestModel getInstance() {
        if (model== null) {
            model= new TestModel ();
        }
        return model;
    }

    @Override
    public  String doData() {

        return "mvp架构";
    }
}

  • 创建一个类,让Activity实现V接口对象,初始化P
public class TestActivity extends AppCompatActivity implements TestContract.View {

    private TestContract.Presenter mPresenter;
    private TextView mDownload;
    private TextView mShowData;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mPresenter = new TestPresenter(TestModel.getInstance(),this);
        mDownload = (TextView) findViewById(R.id.download_data);
        mShowData = (TextView) findViewById(R.id.show_text);
        mDownload.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mPresenter.getData();
            }
        });
    }

    @Override
    public void showData(String str) {
        mShowData.setText("幺幺最爱宝宝");
    }
}

这里就实现了一个简易的MVP架构,三层之间的调用顺序为view->presenter->model

3. 温饱版MVP模式

前述的MVP模式会存在一些问题,其代码冗余量大,且存在内存泄漏的问题,应用请求网络数据时需要等待后台反馈数据后更新界面,但是请求过程中Activity因为某种原因被销毁了,Presenter收到后台反馈并调用View接口处理UI逻辑时,因为Activity已经被销毁了,就会引发空指针异常。

解决这个方法,我们可以将P层与V层绑定起来,每次调用View前都知道宿主Activity的生命状态

  • 修改P接口,增加与View解绑的接口方法:
public interface TestContract {
    interface View {
        //显示数据
        void showData(String str);

    }

    interface Presenter  {
        //通知model要获取数据并把model返回的数据交给view层
        void getData();
        void detach();  //与view解绑

    }

    interface Model {
        //获取数据
        String doData();

    }
}

  • 修改P层代码,在调用View接口对象时,增加一个对对象判断处理,判断View是否被销毁

public class TestPresenter implements TestContract.Presenter {

    private TestContract.Model model;
    private TestContract.View view;

    public TestPresenter (TestContract.Model model, TestContract.View view) {
        this.model = model;
        this.view = view;
    }


    @Override
    public void getData() {
        if (isViewExist(view)) {
            view.showData(model.doData());
        }
    }

    @Override
    public void detach() {
        view = null;
    }

    //判断View是否被销毁
    private boolean isViewExist(TestContract.View view) {
        return view != null;
    }

}
  • 最后,修改V层代码,增加Activity销毁时解绑处理
@Override
    protected void onDestroy() {
        super.onDestroy();
        mPresenter.detach();

    }

这样子我们就解决了内存泄漏的问题。这种情况下的MVP模式基本上是比较完整的,但是还是不够好。应用中肯定不只一个模块,每个模块都对应着一个V层和P层,这样每个Presenter中都要定义绑定解绑方法,造成代码冗余。因此我们可以抽取一个基类来做这些事情,这就引申出了我们的小康版MVP模式

4. 小康版MVP模式

  • 创建一个基类View,让所有View接口都必须实现,这个View可以什么都不做只是用来约束类型
public interface BaseView {
}
  • 创建一个基类的Presenter,在类上规定泛型,定义绑定与解绑方法,然子类去实现。
public class BasePresenter<T extends BaseView> {
    // V层的引用
    protected T mView;

    public BasePresenter(T t) {
        this.mView = t;
    }

    /**
     * 判断是否与View建立连接
      */
    public boolean isViewAttached() {
        return mView!= null;
    }

    /**
     * 销毁View 避免P层在View销毁的时候还持有View对象
     */
    public void destroy() {
        mView = null;
    }
}

  • 撰写契约类Contract
    编写契约类,在契约类中,不会实现任何功能,这里只是写明了Presenter和View分别要实现的接口,这里我们来模拟一个数据下载情况:
/**
 * 数据详情获取
 */
public interface DownloadDataContract {

    interface View extends BaseView {
        void hideLoading(); //  隐藏正在加载的进度框
        void showData(String data);    //  数据请求成功,调用此接口显示数据
        void showFailureMessage(String msg);   // 数据请求失败,提示失败原因
        void showErrorMessage();    //  数据请求异常,提示异常原因
    }

    abstract class Presenter extends BasePresenter<View> {

        public Presenter(View view) {
            super(view);
        }
        public abstract void onSuccess(String data);    //  数据请求成功
        public abstract void onFailure(String msg);     //  数据请求失败
        public abstract void onError();     //  数据请求错误
        public abstract void onComplete();     //  数据请求结束

    }
}
  • Write P level code, it inherits P realized interface method:

public class DownLoadDataPresenter extends DownloadDataContract.Presenter {

    public DownLoadDataPresenter(DownloadDataContract.View view) {
        super(view);
    }

    @Override
    public void onSuccess(String data) {
        if (isViewAttached()) {
            mView.showData(data);
        }
    }

    @Override
    public void onFailure(String msg) {
        if (isViewAttached()) {
            mView.showFailureMessage(msg);
        }
    }

    @Override
    public void onError() {
        if (isViewAttached()) {
            mView.showErrorMessage();
        }
    }

    @Override
    public void onComplete() {
        if (isViewAttached()) {
            mView.hideLoading();
        }
    }
}

  • Write V type layer, holding layer object P, the UI logic:

public class MainActivity extends AppCompatActivity implements DownloadDataContract.View {

    private DownLoadDataPresenter mDownloadDataPresenter;
    private TextView mDownloadDataTv;
    private TextView mShowDataTv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDownloadDataTv = (TextView) findViewById(R.id.download_data);
        mShowDataTv = (TextView) findViewById(R.id.show_text);
        mDownloadDataPresenter = new DownLoadDataPresenter(this);
        mDownloadDataTv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDownloadDataPresenter.onSuccess("you are the best");
            }
        });

    }

    @Override
    public void hideLoading() {

    }

    @Override
    public void showData(String data) {
        mShowDataTv.setText(data);
    }

    @Override
    public void showFailureMessage(String msg) {

    }

    @Override
    public void showErrorMessage() {

    }
}

The MVP pattern Regal Edition

In general, for most projects, the MVP mode version of the well-off can be a good deal with the problems encountered and good structure and reusability of code, of course, there are some imperfections here can be optimized, here you can come out of our rich version of MVP mode.

For the rich version of MVP mode, the main implementation , a senior abstract - Use annotations, factory model, agent model, the strategy pattern to solve the overall code redundancy, memory leaks, Presneter life cycle and data storage issues.

On top rich version of the MVP model to be updated. . . . .

Guess you like

Origin blog.csdn.net/weixin_43499030/article/details/90300070