常用Android架构设计模式(二)MVP模式

前言#

昨天我们已经了解了MVC模式,也大概分析一下MVC模式的优点和不足,确实在android中MVC使用起来会有点怪怪的,于是出现了MVP模式。

MVP模式是MVC衍生出来的新模式,也是为了弥补MVC在设计上的不足之处,把Model和View进一步解耦,提高代码整体的维护性。

正文#

首先还是先来看一下架构图:

这里写图片描述

诶,从架构图上看,跟之前的MVC已经有了很明显的不同,可以总结一下几点:

1、Presenter作为媒介处于Model和View之间,在中间进行综合调度,跟MVC相比,Presenter已经不是一个简简单单的路人甲了,开始掌控全局。

2、Model和View的耦合性变低,更加方便之后维护。

ok,再来了解一下这三个分别承担的任务:

Model:处理要显示的内容(与MVC无变化)
View:负责界面上内容的显示
Presenter:负责整体的逻辑功能和显示变化

概念我们已经弄清楚了,还是要实际操作一下,那我们先准备些什么呢?

MainModel:负责处理一些任务和运算。
MainPresenter:负责整体的功能逻辑调度。
MainActivity:负责View具体的显示工作。

发现了没有?MainActivity扮演的角色已经和MVC完全不一样了,现在是位于View层,这个一定要注意,不要被两种模式弄得一脸懵逼。

按照我的习惯,还是先写View层,MainActivity的代码:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private MainActivityPresenter presenter;

    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = (TextView) findViewById(R.id.textView);
        textView.setOnClickListener(this);
        presenter = new MainActivityPresenter(this);
        presenter.startLoading();
    }

    public void setText(String text){
        textView.setText(text);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        presenter.onDestroy();
    }

    @Override
    public void onClick(View v) {
        presenter.showToast();
    }
}

没有比这更简单的代码了,MainActivity除了初始化View以外,功能逻辑都是调用的Presenter,例如,loading,onClick等等。

然后看看MainPresenter:

/**
 * Created by li.zhipeng on 2017/3/24.
 * <p>
 * MainActivity的Presenter层
 */
public class MainActivityPresenter extends BasePresenter implements OnCallbackListener {

    private MainActivity mainActivity;


    public MainActivityPresenter(MainActivity activity) {
        this.mainActivity = activity;
    }

    public void startLoading() {
        MainActivityModel.login("lzp", "lzp", this);
    }

    @Override
    public void onSuccess() {
        mainActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (checkActivityValid()) {
                    mainActivity.setText("Loading success");
                }
            }
        });
    }

    @Override
    public void onFailed() {
        mainActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (checkActivityValid()) {
                    mainActivity.setText("Loading failed");
                }
            }
        });
    }

    @Override
    public void onLoading() {
        mainActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (checkActivityValid()) {
                    mainActivity.setText("Loading...");
                }
            }
        });
    }

    public void showToast(){
        Toast.makeText(mainActivity, "屌爆了哦~~~", Toast.LENGTH_SHORT).show();
    }

    private boolean checkActivityValid() {
        return mainActivity != null;
    }

    @Override
    public void onDestroy() {
        mainActivity = null;
    }

}

也很简单,定义了登录login方法,并且处理MainModel处理之后的回调,通知MainActivity改变显示效果,还提供了刚才了的onClick事件调用的showToast()方法,核心的逻辑都在Presenter中。

最后就是MainModel:

/**
 * Created by li.zhipeng on 2017/3/24.
 *
 *      MainActivity的Model
 */
public class MainActivityModel {

    /**
     * 提供模拟的网络请求类
     * */
    public static void login(final String name, final String pwd, final OnCallbackListener callbackListener){

        new Thread(){
            @Override
            public void run() {
                callbackListener.onLoading();
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                if (name.equals("lzp") && pwd.equals("lzp")){
                    callbackListener.onSuccess();
                }
                else{
                    callbackListener.onFailed();
                }
            }
        }.start();
    }
}

处理了login方法中具体的逻辑,于是最简单的MVP架构到此结束。

与MVC相比,MVP更加扁平化,三者关系是比较平等的,就好像我们生活中的情景:

View:就是客户,现在需要一批材料。
Model:就是工厂,能够生产View需要的材料
Presenter:中介,在两者之间来回跑。

Presenter对View说:你要想这批材料,你得给我提供一些证明,例如你公司的资质啊,资金啊,需要材料的规模啊,等等。

Presenter对Model说:这是个大活啊,几百万的订单,你得按照规定好好生产啊,别整黄了。

View只负责给Presenter提供证明,如果有问题,直接把Presenter叫过来,问问生产进度(onClick)。

Model只负责生产,拿到Presenter的材料,让我生产啥我就生产啥,干完一单是一单,根本不需要和客户商量,干完了把成果交给Presenter就OK了。

现在的demo是最简单的的MVP,实际上为了把功能模块进一步划分,还有出现Presenterlmpl和ViewImpl,剥夺Presenter和View的完全自主权,就好像突然冒出两个领导,指挥Model和View去做事。

就只看看Presenterlmpl和ViewImpl的代码:

/**
 * Created by li.zhipeng on 2017/3/28.
 *
 *      MainActivity 必要要提供的方法
 */

public interface MainView {

    void setText(String text);
}

/**
 * Created by li.zhipeng on 2017/3/28.
 *
 *      MainPresenter 要实现的功能
 */

public interface MainPresenter {

    void startLoading();

    void showToast();

    boolean checkActivityValid();
}

// 实现对应的接口
public class MainActivity extends AppCompatActivity implements MainView, View.OnClickListener {...}

// 实现对应的接口
public class MainPresenterImpl extends BasePresenter implements MainPresenter, OnCallbackListener {...}

这样进一步分离之后,如果要增加方法必须要先向领导申请,例如MainView添加一个新方法,然后下属才能去做,例如MainActivity具体去实现这个方法。

总结#

到此为止,MVP模式的介绍就结束了,我们来和MVC对比一下:

优点:
1、Model和View进一步解耦,方便扩展和维护。
2、代码模块分工更细,presenter是整体的核心,代码的可读性增强了。

缺点:
1、代码量又增加了!!!

MVP确实弥补了MVC的一些缺点和不足,虽然也需要模块划分,工作量是提高了不少,但是逻辑性有了更清楚的思路,不会像之前一样掺杂在一起。

下一篇,来聊一聊MVVM还有其他的一些东西,综合的聊一聊设计模式。

源码点击下载

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容