• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > MVP模式在Android开发中的最佳实践

MVP模式在Android开发中的最佳实践

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了android mvp设计模式,android mvp模式,android中mvp模式,android mvp开发模式,android mvp模式视频等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

MVP模式在Android开发中的最佳实践


这篇文章拖了好久了,一直存在草稿箱里没有继续写,趁今天有空,撸撸完。

回想一下,你刚刚学习Android的时候,总会看到一些书上写着,Android使用的是MVC模式,Activity就是一个Controller,或许那个时候,你没有什么深刻的体会。随着经验的积累。你发现,Activity既是Controller,掌管着许许多多的业务逻辑,同时它也作为View的一部分,控制着视图层的显示。久而久之,这个Controller便显得过于重,职责不再那么单一。

于是,再后来,为了使Activity的职责更加单一,便出现了MVP,MVVM等模式,只能说各有各的优点,没有谁对谁错,一个模式有另一个模式不具有的特点,同时也不具备另一个模式具有的特点,架构的选择永远是根据业务的复杂程度来进行的。MVC有其特点,就是写代码简单啊,但是其缺点也很明显,业务复杂起来后,Activity显得过于庞大不是特别好维护。至于MVVM,个人是十分排斥这种模式的,为什么呢,在XML中写数据绑定的代码显得有点蛋疼,从而使得xml的职责不是那么单一,在我看来,xml用来作为View再好不过了,不必掺和其他任何元素进来,这样显得“不干净”。而MVP呢,我觉得在Android开发中,MVP是一个值得考虑的模式,它既没有MVVM那样,在xml中写数据绑定的代码,xml依然还是原来的配方,也没有MVC那样,拥有一个臃肿的Controller,取而代之的是更加清晰的分层,职责更加单一,当然,优点背后必然有缺点,相信用过MVP的都知道有什么缺点,那就是接口的定义会暴增。

那么什么是MVP模式呢?

M即Model,what to show? 也就是显示在UI上的数据,至于数据怎么来,数据库,网络等等渠道,都是属于这一层

V即View,how to show?也就是怎么显示数据,在Android中,通常是使用xml定义这个view,一般View中会持有Presenter的引用。

P即Presenter,Presenter扮演着中间联系人的作用,就好比MVC中的Controller,通常来说,Presenetr中一般会持有View和Model的引用。

这三者的联系如下图所示:

这里写图片描述

那么问题来了,该如何实现MVP模式呢?这里介绍一个开源库Mosby,github地址https://github.com/sockeqwe/mosby

本篇文章不对该库的具体实现作分析,如果对实现感兴趣的可以阅读源码,毕竟源码之前,了无秘密。在使用前,先加入对该库的依赖

dependencies {
    compile 'com.hannesdorfmann.mosby:mvp:2.0.1'
    compile 'com.hannesdorfmann.mosby:viewstate:2.0.1'
}

现在假设我们实现一个登陆功能,原来的MVC方式就是先定义好xml,然后直接在Activity中书写各种业务逻辑,导致Activity越来越庞大,而使用了MVP之后,Activity会显得十分干净。

XML的定义这里就不再贴了,两个输入框(账号和密码),一个登陆按钮。

首先,我们需要一个与服务器交互的接口,为了简单起见,我们在本地进行模拟,如果账号密码都是admin,则登陆成功,如果账号密码都是server,其他情况都返回账号或密码错误。理论上,这个需要在子线程中发起请求,再通过UI线程回调,这一步也省略,直接在主线程中判断并回调,由于是本地模拟,不会产生任何卡顿,实际使用时需严格按照子线程请求主线程回调。

public interface Listener {
    void onSuccess(T t);

    void onFailure(int code);
}
public class LoginApi {
    public static void login(String username, String password, Listener listener) {
        if (username.equals("admin") && password.equals("admin")) {
            listener.onSuccess(null);
        } else if (username.equals("server") && password.equals("server")) {
            listener.onFailure(LoginView.SERVER_ERROR);
        } else {
            listener.onFailure(LoginView.USERNAME_OR_PASSWORD_ERROR);
        }
    }
}

业务逻辑的接口定义好了,这个LoginApi可以认为是Model层,接下来我们需要定义和Login相关的View,Presenter。

首先定义一个LoginView接口继承MvpView接口,由于登录的接口有两种情况,一种是登录成功,一种是登录失败,而登录失败的情况又有多种,于是需要通过一个状态码进行区分,于是LoginView中的接口就产生了。这里我们直接将各种错误状态定义在了LoginView中,实际使用时建议定义在一个常量类中进行统一管理。

public interface LoginView extends MvpView {

    public static final int USERNAME_OR_PASSWORD_EMPTY = 0x01;
    public static final int USERNAME_OR_PASSWORD_ERROR = 0x02;
    public static final int SERVER_ERROR = 0x03;

    void onLoginSuccess();

    void onLoginFailure(int code);
}

然后定义一个LoginPresenter类继承MvpBasePresenter,泛型参数是LoginView,在里面调用LoginApi的接口并将接口返回。

public class LoginPresenter extends MvpBasePresenter {

    public void login(final String username, final String password) {
        if (username == null || username.equals("")) {
            LoginView view = getView();
            if (view != null) {
                view.onLoginFailure(LoginView.USERNAME_OR_PASSWORD_EMPTY);
                return;
            }
        } else if (password == null || password.equals("")) {
            LoginView view = getView();
            if (view != null) {
                view.onLoginFailure(LoginView.USERNAME_OR_PASSWORD_EMPTY);
                return;
            }
        }
        Listener listener = new Listener() {
            @Override
            public void onSuccess(String str) {
                LoginView view = getView();
                if (view != null) {
                    view.onLoginSuccess();
                }
            }

            @Override
            public void onFailure(int code) {
                if (code == LoginView.USERNAME_OR_PASSWORD_ERROR) {
                    LoginView view = getView();
                    if (view != null) {
                        view.onLoginFailure(LoginView.USERNAME_OR_PASSWORD_ERROR);
                    }
                } else {
                    LoginView view = getView();
                    if (view != null) {
                        view.onLoginFailure(LoginView.SERVER_ERROR);
                    }
                }
            }
        };
        LoginApi.login(username, password, listener);
    }
}

最后便是让Activity实现LoginView接口,实现LoginView中定义的接口,此外,还需要继承MvpActivity,泛型参数是LoginView和LoginPresenter,并实现抽象方法createPresenter()返回LoginPresenter,而在LoginView中定义的两个接口onLoginSuccess和onLoginFailure中,全都是UI相关的代码,整个Activity中不再有业务逻辑的代码,职责也就单一了。

public class LoginActivity extends MvpActivity implements View.OnClickListener, LoginView {
    private EditText etAccount;
    private EditText etPassword;
    private Button btnLogin;

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

        etAccount = (EditText) findViewById(R.id.accout);
        etPassword = (EditText) findViewById(R.id.password);
        btnLogin = (Button) findViewById(R.id.login);
        btnLogin.setOnClickListener(this);

    }

    @NonNull
    @Override
    public LoginPresenter createPresenter() {
        return new LoginPresenter();
    }


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

        }
    }

    private void onLogin() {
        String username = etAccount.getText().toString();
        String passowrd = etPassword.getText().toString();
        getPresenter().login(username, passowrd);
    }


    @Override
    public void onLoginSuccess() {
        Toast.makeText(this, "登陆成功", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onLoginFailure(int code) {
        switch (code) {
            case LoginView.USERNAME_OR_PASSWORD_EMPTY:
                Toast.makeText(this, "账号或密码不能为空", Toast.LENGTH_SHORT).show();
                break;
            case LoginView.USERNAME_OR_PASSWORD_ERROR:
                Toast.ma



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • android中常见的设计模式有哪些?,android设计模式
  • MVP解析,mvp模式解析实践
  • Android MVP 设计模式,androidmvp
  • MVP模式在Android开发中的最佳实践

相关文章

  • 2017-05-222.3.8 SeekBar(拖动条)
  • 2017-05-26做了5年软件测试了,写写心得
  • 2017-05-26浅谈Kotlin(三):类,浅谈kotlin
  • 2017-05-26Android之SQLite数据存储,androidsqlite
  • 2017-05-26如何取得nginx做反向代理时的真实IP?
  • 2017-05-26二维码Zxing&Zbar,zxing
  • 2017-05-26Android中TextView设置最大长度,超出显示省略号,androidtextview
  • 2017-05-26android 在5.0以后不允许使用隐式Intent方式来启动Service,androidintent
  • 2017-05-26翻翻git之---一个丰富的通知的工具库 NotifyUtil
  • 2017-05-26Android中使用ExpandableListView实现好友分组,expandablelistview

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 历代安卓版本回顾(使用者角度+开发者角度)长期更新!!!,安卓开发者
    • andriod 动态显示当前时间,andriod当前时间
    • 安卓开源项目周报0411,安卓开源项目0411
    • 《第一行代码》目录
    • 插入排序算法详解,排序算法详解
    • Android动态加载Dex机制解析
    • Android入门(九)文件存储与SharedPreferences存储,
    • Android的Dialog工具
    • [Android]Animation 动画介绍和实现,androidanimation
    • 在Android应用程序使用YouTube API来嵌入视频,

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有