Android 初识mvp设计模式

    xiaoxiao2021-03-25  53

        今天打开最近一直在写的项目,发现项目的结构乱得很,有的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中的MVP/

    转载请注明原文地址: https://ju.6miu.com/read-50347.html

    最新回复(0)