MVP模式是否适合我们使用? 代码说话

转载请注明出处:王亟亟的大牛之路

按照惯例今天上了一个关于沉浸式菜单栏的文章的就不写了,然后 下班前看到一些感兴趣的内容就研究了下,MVP模式之前有大致的了解但是没有实战的在安卓上用过。(国内也有一些大牛有些过类似的内容,但是每个人对一件事情的理解可能大致相同但是总有细微的差异,主要是把我对这件东西的理解和实现方式分享给大家)

我不太喜欢搬太多人家已经整理好的东西再贴出来搞的自己理论多牛B,我还是用代码和例子说话,那么这里留下一些别人讲过的概念性的东西给大家建立概念,这些设计层面的东西还是希望大家看完再来看代码,不然直接看代码的话第一反应就是没事找事。。。

翔哥:http://blog.csdn.net/lmj623565791/article/details/46596109
Rocko:http://rocko.xyz/2015/02/06/Android%E4%B8%AD%E7%9A%84MVP/

OK,先上下效果图

合理操作的情况下

这里写图片描述

少输东西的情况下

这里写图片描述

强迫症所迫,我尽量保证我的例子本身就是有内容的,至少不是随便拖2个“土”的要死的控件就用的,所以写到现在(5点下班现在都8点多了。。肚子好饿。。)

先上下我们用到的库(都是之前我有讲过的,再次感谢开源的大腿们!!)

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.2.1'
    compile 'com.android.support:design:23.2.1'
    compile 'com.rengwuxian.materialedittext:library:2.1.4'
    compile 'com.jaeger.statusbaruitl:library:1.0.0'
    compile 'com.jakewharton:butterknife:7.0.1'
    compile 'com.apkfuns.logutils:library:1.2.2'
}

再看看包目录

这里写图片描述

其实只有2个Activity 一个登录一个主页面,Login目录下的全是用于登陆的(此时,下面一阵哗然,我X 怎么一个登录 那么多类/接口)

这里考虑了好久还是觉得源码直接贴在这里比较合适,方便参照理解(名字没取好,我的锅)

负责登录的Activity

public void UserNameError()  //处理用户名错误
public void PassWordError()  //处理密码错误
public void LoginSuccess()  //登陆成功跳转
public class LoginActivity extends AppCompatActivity implements LoginLogic {

    @Bind(R.id.fab)
    FloatingActionButton fab;
    @Bind(R.id.passWord)
    MaterialEditText passWord;
    @Bind(R.id.userName)
    MaterialEditText userName;
    ClickInterface clickInterface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        ButterKnife.bind(this);
        StatusBarUtil.setTransparent(this);
        clickInterface = new LoginControl(this);
    }

    @OnClick(R.id.fab)
    public void Login(View view) {
        LogUtils.d("--->fab Login");
        clickInterface.Login(userName.getText().toString().trim(), passWord.getText().toString().trim());
    }

    @Override
    public void UserNameError() {
        userName.setError("用户名有误");
    }

    @Override
    public void PassWordError() {
        passWord.setError("密码有误");
    }

    @Override
    public void LoginSuccess() {
        MainActivity.LogicSuccess(LoginActivity.this);
    }
}

用户按钮触发,传入账号和密码的2个字符串

public interface ClickInterface {
    void Login(String userName, String passWord);
}

前面试图层所调的接口

public interface LoginLogic {

    void UserNameError();

    void PassWordError();

    void LoginSuccess();
}

实现类返回结果所用的接口 OnLoginFabClick 具体执行登陆操作的方法 doLogin()

public interface LogicInterface {

    interface OnLoginFabClick {

        void OnUserNameError();

        void OnPasswordError();

        void OnLoginSuccess();
    }

    void doLogin(String userNameStr, String passwordStr, OnLoginFabClick onLoginFabClick);
}

“中央处理器”做2种流程的中转站,作为试图层和操作层的中转站

public class LoginControl implements LoginInterfaceImp.OnLoginFabClick, ClickInterface {

    LoginLogic loginLogic;
    LogicInterface logicInterface;

    public LoginControl(LoginLogic loginLogic) {
        this.loginLogic = loginLogic;
        this.logicInterface = new LoginInterfaceImp();
    }

    @Override
    public void OnUserNameError() {
        loginLogic.UserNameError();
    }

    @Override
    public void OnPasswordError() {
        loginLogic.PassWordError();
    }

    @Override
    public void OnLoginSuccess() {
        loginLogic.LoginSuccess();
    }

    @Override
    public void Login(String userName, String passWord) {
        logicInterface.doLogin(userName, passWord, this);
    }
}

具体做登陆行为的实现类,点击事件的最终目的地以及事件反馈的起点

/**
 * Created by jiajiewang on 16/3/29.
 */
public class LoginInterfaceImp implements LogicInterface {


    @Override
    public void doLogin(String userNameStr, String passwordStr, OnLoginFabClick onLoginFabClick) {
        boolean flag = true;
        if (userNameStr.length() < 1 || userNameStr == null) {
            onLoginFabClick.OnUserNameError();
            flag = false;
        }
        if (passwordStr.length() < 1 || passwordStr == null) {
            onLoginFabClick.OnPasswordError();
            flag = false;
        }
        if (flag) {
            onLoginFabClick.OnLoginSuccess();
        }
    }


}

什么?贴了一大堆不是具体的项目 不能 点进去看概念不清?

为了防止大家有类似的疑问我给大家画了,重要的事情用大大大字!!

总流程:

这里写图片描述

总流程是不是很抽象对具体的行为不是很清楚? 没事 我 把2条任务线都打通了

这条线称之为“命令去做登陆流程线

这里写图片描述

这条称之为“告诉试图可不可以登录流程线

这里写图片描述

看完这3张图你明白做了些什么事了吧?
你:“不明白”

那我告诉你为什么要这样设计要这么做?

1.层次分明,各层级之间都不管对方如何实现,只关注结果;
2.在视图层(Presentation Layer)使用MVP架构,使原本臃肿的Activity(或Fragment)变得简单,其处理方法都交给了Presenter。
3.易于做测试,只要基于每个模块单独做好单元测试就能确保整体的稳定性。
4.易于快速迭代,基于代码的低耦合,只需在业务逻辑上增加接口,然后在相应的层级分别实现即可,丝毫不影响其他功能。

什么?这么说太官方?那我来再来举一个例子,我们现在只有按钮一个然后他从ClickInterface 这条线发出去了,那我有好多好多的按钮好多好多的行为呢? 只需要在ClickInterface 里面加所需的方法就行了,完全不用整个项目这个类改那个类改。

虽然搭建的过程有点恶心+难建设,但是只要这么搭完后面的事情就水到渠成了!

这里补几张隔壁扣来的原理图:

这里写图片描述

这里写图片描述

源码地址:https://github.com/ddwhan0123/BlogSample/blob/master/MVPDemo.zip

下班啦!!!!!!

当然如果你还有不理解的可以直接微信我真人(不xu恶意骚扰)

这里写图片描述

OH,吼一句,收Java Web PHP,找工作的也可以考虑下哦!

评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值