Android 初识mvp设计模式

2 篇文章 0 订阅
2 篇文章 0 订阅

    今天打开最近一直在写的项目,发现项目的结构乱得很,有的java文件看起来竟压根记不起写的什么意思,所幸想起了之前群里大神提及的mvp设计模式,于是便在网上找了篇大神写的mvp模式的文章。那篇文章的篇幅还是蛮长的,说实话,由于之前压根没接触过mvp甚至mvc,看了第一遍压根没看懂多少,于是结合着mvp与mvc设计的模型以及小项目看了一遍,终于有了些眉头,于是,便在android studio上试着写了该项目,加深了一些印象和理解。现在回想一下,mvp虽然增加了代码的宏观复杂使用,包括类、接口、继承与实现的熟练应用等内容,但是代码功能划分以及设计划分更加清晰并增加了代码的复用性,明显是利大于弊。

1.什么是mvp?

概念:MVP 指的是Model,View,Presenter(交互器/表示器),是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。

2.MVP与MVC的区别

MVC:

  • View:对应于布局文件
  • Model:业务逻辑和实体模型
  • Controllor:对应于Activity
view对应的是布局文件,这里涉及到的功能过于单一,做的事情只有显示界面这一种事情,没有简单的逻辑处理;涉及到布局中控件的数据绑定和处理都集中在activity中,这就使得activity中内容过于冗杂和沉重,搞的activity好像是做了相当于view和controller两个人的事情,让我们来看下MVP在其基础上做了哪些改进。

MVP:

  • View 对应于Activity,负责View的绘制以及与用户交互
  • Model 依然是业务逻辑和实体模型
  • Presenter 负责完成View于Model间的交互
从中可以看出,mvp中的view由activity来承担,activity中只涉及到view显示和简单的逻辑操作,而复杂的view逻辑处理则交给了presenter来处理和实现,大大降低了耦合度


借用了大神的一张图,从中可以看出MVP与MVC的区别:
MVC中是允许Model和View进行交互的,而MVP中很明显,Model与View之间的交互由Presenter完成,还有一点就是Presenter与View之间的交互是通过接口来实现的,更重要的是,后者降低了activity的负担,这对于代码后期易读性和复用性无疑是很好的帮助。
还是通过最简单的demo来实现一下加深理解吧,以后再翻过来多看几遍。

3.通过demo加深理解

先来看下demo的实现效果:


这样的登录小demo不用mvp实现的确简单至极,但是用mvp却要考虑很多方面,view,presenter,model,以及各层之间的分工合作关系。

再来看下项目的结构:


通过这样的结构来看,给人明显的感觉就是项目划分很明确,思路清晰,所以,后面打算一直尝试着用mvp模式来写代码了,这是一个良好的习惯。

4.具体代码

功能代码理解起来没什么困难,主要是要理解其核心的设计思想以及设计角度,如何将三层联系起来,这还要靠后面的项目慢慢积累经验。

就直接贴代码了:

  • Model层实现
1.User实体类

package test.mvptest.bean;
/**
 * Created by Administrator on 2017/3/14.
 * 用户的实体类
 */

public class User {
    private String account;//用户帐号
    private String password;//用户密码
    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }



}
2.业务处理

先写一个接口InUserLogic提供业务逻辑方法供实现类来实现,里面只有一个goLogin()方法,其中有三个参数,前两个主要用来传入文本框内容与数据库内容进行核对,最后一个是一个回调接口,用来返回登录成功或者失败的信息通知。

1).接口InUserLogic

package test.mvptest.logic;

/**
 * Created by Administrator on 2017/3/14.
 * 用户的业务逻辑接口
 * 实现业务:登录
 */

public interface InUserLogic {
    public void goLogin(String account,String password,OnLoginListener onLoginListener);//业务处理方法:用户的登录
}
2).其次是它的实现类UserLogic:

package test.mvptest.logic;

import test.mvptest.bean.User;

/**
 * 各层的交互主要通过接口来实现
 * Created by Administrator on 2017/3/14.
 */

public class UserLogic implements InUserLogic {
    @Override
    public void goLogin(final String acc, final String pass, final OnLoginListener onLoginListener) {
        //模拟子线程的相关耗时操作
        new Thread(){
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //如果登录成功的业务逻辑操作
                if ("123".equals(acc)&&"123".equals(pass)){
                    User user=new User();
                    user.setAccount(acc);
                    user.setPassword(pass);
                    onLoginListener.loginSuccess(user);//回调登录成功的相关操作

                }else{
                    onLoginListener.loginFailed();//回调登录失败的操作
                }
            }
        }.start();//记得启动
    }
}
3.最后是回调信息接口

主要涉及两个方法:onSuccess()和onFailed()判断登录成功与失败

package test.mvptest.logic;

import test.mvptest.bean.User;

/**
 * Created by Administrator on 2017/3/14.
 * 定义一个用户登录的回调接口,用于返回通知登录状态
 */

public interface OnLoginListener {
    public void loginSuccess(User user);//登录成功的回调
    public void loginFailed();//登录失败的回调
}
  • View层实现
view主要是由布局文件和activity实现的,而activity可以实现一个view接口InLoginView,里面定义一些iew要实现的界面效果处理逻辑方法,然后由activity实现

1).InLoginView接口

思考界面的显示需要用到哪些方法?
仔细看一下界面,主要构成有:两个按钮(登录和清除)+两个文本框+进度条。那么肯定是与它们有关的方法,即:获取文本框的内容(getAccount+getPassword),
 按钮实现登录和清除(登录成功的跳转intentTo+失败提醒showFailedError;清除文本框内容clearText;showProgress+hideProgress)

public interface InLoginView {
    public String getAccount();
    public String getPassword();
    public void intentTo(User user);
    public void showFailedError();
    public void clearText();
    public void showProgress();
    public void hideProgress();
}
2)activity中view初始化和方法实现

activity中涉及到的复杂的逻辑代码被提取到了后面的Presenter中进行处理,从而减少了Activity的职责,简化了Activity中的代码。

其中涉及到的主要逻辑操作就是登录与清除了

public class MainActivity extends AppCompatActivity implements View.OnClickListener, InLoginView {
    private EditText account;
    private EditText password;
    private ProgressBar progressBar;
    Button login,clear;
    private LoginPresenter loginPresenter=new LoginPresenter(this);;
/*
 实现InLoginView的接口,然后通过presenter传入当前view对象来在activity之外实现对view的逻辑操作
 */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }
    private void initView(){//初始化view
        account= (EditText) findViewById(R.id.editText);
        password= (EditText) findViewById(R.id.editText2);
        progressBar= (ProgressBar) findViewById(R.id.progressBar);
        login= (Button) findViewById(R.id.login);
        clear= (Button) findViewById(R.id.clear);
        login.setOnClickListener(this);
        clear.setOnClickListener(this);


    }


    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.login:
                loginPresenter.login();

                break;
            case R.id.clear:
                loginPresenter.clear();

                break;
        }

    }

    @Override
    public String getAccount() {
        return account.getText().toString();
    }

    @Override
    public String getPassword() {
        return password.getText().toString();
    }

    @Override
    public void intentTo(User user) {
        Toast.makeText(this,user.getAccount()+"登陆成功!",Toast.LENGTH_SHORT).show();

    }

    @Override
    public void showFailedError() {
        Toast.makeText(this,"登陆失败!",Toast.LENGTH_SHORT).show();

    }

    @Override
    public void clearText() {//清空文本框
        account.setText("");
        password.setText("");

    }

    @Override
    public void showProgress() {
        progressBar.setVisibility(View.VISIBLE);

    }

    @Override
    public void hideProgress() {
        progressBar.setVisibility(View.GONE);

    }
}
  • Presenter层实现
前面已经说过,Presenter用于实现M与V的交互,可以实现activity中复杂的逻辑代码
所以,仔细想想activity有什么操作,对的,还是登录与清除功能模块的逻辑。
public class LoginPresenter {
    InUserLogic inUserLogic;//业务逻辑
    InLoginView inLoginView;//界面
    private Handler handler=new Handler();
    public LoginPresenter(InLoginView loginView){
        this.inLoginView=loginView;
        this.inUserLogic=new UserLogic();//新建一个实现接口类的对象
    }
    public void login(){
        inLoginView.showProgress();
        inUserLogic.goLogin(inLoginView.getAccount(), inLoginView.getPassword(), new OnLoginListener() {
            @Override
            public void loginSuccess(final User user) {
                //线程这块还要多看看,很快就忘了
                //需要在ui线程执行
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        inLoginView.intentTo(user);
                        inLoginView.hideProgress();
                    }
                });
            }

            @Override
            public void loginFailed() {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        inLoginView.showFailedError();
                        inLoginView.hideProgress();
                    }
                });

            }
        });
    }
    public void clear(){
        inLoginView.clearText();
    }


}
构造方法里涉及到两层对象的初始化,最后在activity中新建一个presenter对象,传入当前的view对象,即this。

5.小结:

1).MVP代码的编写模式可以简化activity的工作,让其只负责view实现和简单的逻辑操作,复杂的view逻辑处理交给Presenter来处理,Model层负责数据操作或者相关网络操作以及业务逻辑的处理;Presenter作为M与V交互的桥梁,肯定需要传入二者的实现类,从View中获取需要的参数,交给Model去执行业务方法,执行的过程中需要的反馈(回调),以及结果,再让View进行做对应的显示。
2).MVP给其他人一种清晰感,尤其面对庞大的项目不必再因为activity里繁杂的变量方法而头疼,更有助于代码的复用性以及逻辑功能的思路清晰,日后得多加尝试使用。

补充:本文仅用来记录日常所学,方便日后查看方便,同时也参考了一些文章,供大家借鉴一下吧,有问题或者改进之处还请提出,谢谢。

参考文章:

http://blog.csdn.net/lmj623565791/article/details/46596109?spm=5176.100239.0.0.NCNXl0#comments

http://www.cnblogs.com/android-zcq/p/5126925.html

https://rocko.xyz/2015/02/06/Android%E4%B8%AD%E7%9A%84MVP/

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值