继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Android架构篇--MVP模式的介绍篇

白板的微信
关注TA
已关注
手记 341
粉丝 70
获赞 385

摘要: 在MVVM成熟之前MVP模式在Android上有被神化的趋势,笔者曾经在商业项目中从零开始大规模采用过MVP模式对项目进行开发。在使用MVP模式进行开发的时候发现项目的结构模式对开发是有一定的影响的,在这里笔者会对这一问题进行探讨。希望通过这篇blog能让读者了解如何使用MVP模式搭建一个功能完善的MVP模式开发框架,避免一些笔者认为比较严重的问题。

为什么要使用MVP模式

在传统的Android开发中,我们一般是使用MVC模式进行开发的。
传统MVC模式介绍:

  1. View: 视图层,对应xml文件

  2. Controller: 控制层,对应Activity和Fragment层,进行数据处理

  3. Model:实体层,负责获取实体数据

在Android开发中采用MVC模式的一个最大的弊端就是xml作为View层视图能力实在太弱,所以一般情况下我们都是通过Controller层来辅助处理一些视图的。这样的结果就导致Controller既作为控制层的同时又承担了View层的大部分功能,采用MVC模式往往会导致Activity和Fragment中的代码非常复杂。我们将Android中采用的MVC模式称为MV模式更加恰当。

MVP模式介绍:

  1. View: 视图层,对应xml文件与Activity/Fragment

  2. Presenter: 逻辑控制层,同时持有View和Model对象

  3. Model: 实体层,负责获取实体数据


采用MVP模式的优势是:

  1. 把业务逻辑抽离到Presenter层中,View层专注于UI的处理。

  2. 分离视图逻辑与业务逻辑,达到解耦的目的。

  3. 提高代码的阅读性。

  4. Presenter被抽象成接口,可以根据Presenter的实现方式进行单元测试。

  5. 可拓展性强。

采用MVP模式的缺点:

  1. 项目结构会对后期的开发和维护有一定的影响。具体视APP的体量而定。

  2. 代码量会增多,如何避免编写过多功能相似的重复代码是使用MVP开发的一个重点要处理的问题。

  3. 有一定的学习成本。

综上所述,在Android上采用MVP模式的优势是:大大优化代码的维护性与拓展性的同时对代码进行深度解耦,使各个层级的分工更加明晰。

Android上MVP模式的简单应用

先来看看一个简单用mvp模式模拟登陆的demo,下面的示例代码和其它简单介绍MVP模式的代码没有太大区别。如果有了解过的同学可以直接跳过看下一章关于如何优化MVP模式的结构的文章。

下面我们来看看在Android上用MVP模式实现简单的登录逻辑的方式

从上面的代码结构图可看出,用MVP模式实现登陆模块需要创建6个文件,分别是M、V、P接口文件和接口的对应实现。其中LoginActivity就是View层的具体实现。这样的好处时Activity组件只需要负责处理UI相关逻辑就可以了,而相关的业务逻辑全部抽象到Presenter层中处理。通过这种方式能够很好的避免传统Android开发中的Activity/Fragment等UI组件既负责处理UI逻辑又处理业务逻辑的结果。

. 代码实现

说了这么多,最后我们来看看代码的实现吧。

  1. ILoginModel

    123
    public interface ILoginModel {void login(String name ,String password);}
  2. ILoginPresenter

    123456
    public interface ILoginPresenter {void loginToServer(String userName,String password);void loginSucceed();}
  3. ILoginView

    123456
    public interface ILoginView {void showProgress(boolean enable);void showLoginView();}

上面是登陆模块对应的MVP接口的具体设计,下面我来简单介绍一下接口中的几个方法:

  • ILoginModel.login(String name ,String password)登陆方法,通过该方法向服务器发送登陆请求。

  • ILoginPresenter. loginToServer (String name ,String password)通知Model响应登陆事件。

  • ILoginPresenter. loginSucceed()当登陆事件完成时(成功/失败),Model层要通知该方法登陆事件已完成。

  • ILoginView. showProgress(boolean enable)当Presenter层调用loginToServer (String name ,String password)方法时,要通过该方法通知View层显示加载动画。

  • ILoginView. showLoginView()登陆成功时,Presenter层会通过该方法通知View层登陆已成功。

下面我们来看看这几个接口的具体实现。

  1. LoginModel

    1234567891011121314151617181920212223
    public class LoginModel implements ILoginModel{private ILoginPresenter presenter;private Handler mHandler = new Handler();public LoginModel(ILoginPresenter presenter) {this.presenter = presenter;}@Override  public void login(String name ,String password) {mHandler.postDelayed(new Runnable() {@Override  public void run() {Log.d("LoginModel", "run: ");presenter.loginSucceed();}},2000);}}

上面的Model层实现了login(String name,Stringpassword)登陆方法,该方法的具体实现逻辑是通过线程休眠2秒来模拟网络登陆的过程,登陆成功后会通过LoginPresenter的loginSucceed()方法来通知Presenter层登陆结果。实际开发中我们需要根据具体的业务逻辑来实现该过程。

  1. LoginPresenter

    1234567891011121314151617181920212223
    public class LoginPresenter implements ILoginPresenter{private ILoginModel loginModel;private ILoginView loginView;public LoginPresenter(ILoginView loginView) {this.loginView = loginView;this.loginModel = new LoginModel(this);}@Override  public void loginToServer(String userName, String password) {loginView.showProgress(true);loginModel.login(userName,password);}@Override  public void loginSucceed() {loginView.showProgress(false);loginView.showLoginView();}}

从上面代码可以看出LoginPresenter的实现逻辑很简单,首先在构造方法中获取ILoginView对象并撞见ILoginModel对象。然后当View层调用loginToServer(String userName, String password)方法成功时,通知View层显示加载动画并调用ILoginModel层的login(String userName, String password)方法向服务器发送登陆请求。当登陆成功后(即Model层通知loginSucceed方法时)通过loginView.showProgress(false)方法通知View层隐藏加载动画,并通知View登陆成功。

  1. LoginActivity
    对于LoginActivity我们只需要关注其中的几个方法即可

    1234567
    loginBtn.setOnClickListener(new View.OnClickListener() {@Override  public void onClick(View v) {//模拟登陆,不需要账号密码  loginPresenter.loginToServer("","");}});

12345678910111213141516
@Override  public void showProgress(boolean enable) {if (enable){progressBar.setVisibility(View.VISIBLE);loginLayout.setVisibility(View.GONE);}else {progressBar.setVisibility(View.GONE);loginLayout.setVisibility(View.VISIBLE);}}@Override  public void showLoginView() {Toast.makeText(LoginActivity.this,"登陆功",Toast.LENGTHSHORT).show();finish();}

上面时实现了ILoginView接口的两个方法。
结合上面的代码可以看出,当点击登陆按钮的监听事件时,我们不需要关注业务逻辑,只需要调用loginPresenter.loginToServer("","");方法即可,然后根据实际情况实现View层中ILoginView接口的方法即可,这样达到了UI业务与逻辑完全分离的目的。

小结

关于在Android上应用MVP模式开发的第一篇到这里就结束了。这只是通过简单的例子介绍MVP模式在Android上的应用罢了,读者应该也看出来了,不进行任何处理的情况下使用MVP模式进行开发时相对于传统的MV模式来说代码量与文件数量增加了很多,相信不少同学会纠结在传统MV模式的代码量与MVP模式的逻辑清晰之间。
随着项目的体量变大,逻辑是否清晰会大大影响到我们的开发。笔者在使用MV进行开发时,常常不得不面对几百行甚至上千行代码的Acitvity,所以笔者在这里推荐大家使用MVP模式进行开发。
但是作为一个优秀的码农(其实是因为我很懒)肯定不会满足于这种结果,所以笔者通过不懈的努力研究出一套可以大大减少在使用MVP模式时代码量和文件量的方法,相信在国庆之后会给出第二篇关于优化使用MVP进行开发的文章。这个系列的最终目标是给出一个从零开始搭建一个功能完善的MVP快速开发框架。

原文链接:http://www.apkbus.com/blog-866962-68049.html

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP