【软件架构】通俗易懂的MVP架构讲解

来源:互联网 发布:霍启山评价郭晶晶 知乎 编辑:程序博客网 时间:2024/06/05 09:27

从MVC到MVP再到MVVP,相信大家就已经听说过这些架构了。但你真正应用到哪个阶段了呢?是不是还苦于网上对MVP晦涩的讲解?今天,Coder哥就用最通俗易懂的方式告诉你,MVP怎么用!

先上一张MVP结构图。 
这里写图片描述

接下来就一步步教你用:

1、首先把结构包分好,方便理清思路

这里写图片描述

2、定义Model层的接口IModel

/** * Model层接口---实现该接口的类负责实际的获取数据操作,如数据库读取、网络加载 */public interface IModel {    void getData(Model.LoadDataCallback callback);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

然后创建Model实体类实现IModel接口,并覆写数据获取方法。

/** * 实现IModel接口,负责实际的数据获取操作(数据库读取,网络加载等),然后通过自己的接口(LoadDataCallback)反馈出去 */public class Model implements IModel {    @Override    public void getData(final LoadDataCallback callback) {        //数据获取操作,如数据库查询、网络加载等        new Thread() {            @Override            public void run() {                try {                    //模拟耗时操作                    Thread.sleep(3000);                    //获取到了数据                    String data = "我是获取到的数据";                    //将获取的数据通过接口反馈出去                    callback.success(data);                } catch (InterruptedException e) {                    e.printStackTrace();                    //获取数据失败的回调                    callback.failure();                }            }        }.start();    }    public interface LoadDataCallback {        void success(String taskId);        void failure();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

Model层搞定!

2、定义IView接口

/** * View层接口---执行各种UI操作,定义的方法主要是给Presenter中来调用的 */public interface IView {    void showLoadingProgress(String message);    void showData(String text);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

然后创建View实体类实现IView接口,并覆写UI操作方法。

/** * 实现IView接口并实现各种UI操作的方法(其他的业务逻辑在Presenter中进行操作) */public class ViewActivity extends Activity implements IView {    private Button mBtnShowToast;    private TextView mText;    private MyHandler mHandler = new MyHandler(ViewActivity.this);    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_mvp);        mBtnShowToast = (Button) findViewById(R.id.btn_show_toast);        mText = (TextView) findViewById(R.id.text);        mBtnShowToast.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {            }        });    }    @Override    public void showLoadingProgress(final String message) {        mHandler.post(new Runnable() {            @Override            public void run() {                mText.setText(message);            }        });    }    @Override    public void showData(final String text) {        mHandler.post(new Runnable() {            @Override            public void run() {                mText.setText(text);            }        });    }    private class MyHandler extends Handler {        //弱引用,防止内存泄露        WeakReference<ViewActivity> weakReference;        public MyHandler(ViewActivity activity) {            this.weakReference = new WeakReference<ViewActivity>(activity);        }        @Override        public void handleMessage(Message msg) {            switch (msg.what) {                case 1:                    weakReference.get().mText.setText(msg.what);                    break;            }        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

View层搞定!

3、定义IPresenter接口

/** * Presenter层接口---控制Model层的数据操作及调用View层的UI操作来完成“中间人”工作 */public interface IPresenter {    void loadData();}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

然后创建Presenter实体类实现IPresenter接口。

public class Presenter implements IPresenter, Model.LoadDataCallback {    private final IView mView;    private final Model mModel;    public Presenter(IView view) {        mView = view;        mModel = new Model();    }    @Override    public void loadData() {        mView.showLoadingProgress("加载数据中");        mModel.getData(Presenter.this);    }    @Override    public void success(String data) {        mView.showData(data);    }    @Override    public void failure() {    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

4、View中实例化Presenter,通过Presenter来处理业务逻辑。最终达到,View只负责UI操作,Model只负责数据,Presenter负责链接二者的目的。

View层完整代码

/** * 实现IView接口并实现各种UI操作的方法(其他的业务逻辑在Presenter中进行操作) */public class ViewActivity extends Activity implements IView {    private Button mBtnShowToast;    private TextView mText;    private MyHandler mHandler = new MyHandler(ViewActivity.this);    private IPresenter mPresenter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_mvp);        //实例化Presenter,并将实现了IView接口的类传入进去        mPresenter = new Presenter(ViewActivity.this);        mBtnShowToast = (Button) findViewById(R.id.btn_show_toast);        mText = (TextView) findViewById(R.id.text);        mBtnShowToast.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                //通过Presenter来实现业务逻辑操作,View层只负责UI相关操作                mPresenter.loadData();            }        });    }    @Override    public void showLoadingProgress(final String message) {        mHandler.post(new Runnable() {            @Override            public void run() {                mText.setText(message);            }        });    }    @Override    public void showData(final String text) {        mHandler.post(new Runnable() {            @Override            public void run() {                mText.setText(text);            }        });    }    private class MyHandler extends Handler {        //弱引用,防止内存泄露        WeakReference<ViewActivity> weakReference;        public MyHandler(ViewActivity activity) {            this.weakReference = new WeakReference<ViewActivity>(activity);        }        @Override        public void handleMessage(Message msg) {            switch (msg.what) {                case 1:                    weakReference.get().mText.setText(msg.what);                    break;            }        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68

大家要多看,多试验,最重要的是理解这个思路。Google官方的Todo MVP代码大家可以去研读一下,是同一个模式,只不过它把好多接口集成在一个接口文件中,防止代码碎片化,大家研读时记住这一点,就不会困惑了。

最后附上Google MVP的代码地址:

https://github.com/googlesamples/android-architecture/tree/todo-mvp/