Android MVP+RxJava+Retrofit (1) MVP设计模式

Android MVP+RxJava+Retrofit (1) MVP设计模式

最近做项目都是接别人的二手项目,发现都是MVP设计模式,感觉自己欠下了2017年的技术债,所以有必要写一篇关于MVP设计模式的博客了,在写这篇博客之前,我想了挺久的,MVP这种文章一百度一大堆,也不知道自己写的怎么样,为了加深自己的理解也希望能帮助别人,这是我写文章的初衷。

说道MVP 那必须先说一下MVC

MVC设计模式

事件流向
在这里插入图片描述

在 MVC 架构中,View 产生事件,通知到 Controller,Controller 中进行一系列逻辑处理,之后通知给 Model 去更新数据,Model 更新数据后,再将数据结构通知给 View 去更新界面.

优点: 结构清晰,职责划分清晰,降低耦合,有利于组件重用

缺点: Activity / Fragment 中代码较多,增加代码结构的复杂性.

但是在现实开发中 基本都把业务逻辑扔在了 Activity / Fragment 中 ,很少有人去写Controller.这种写法俗称一把梭.主要是因为开发进度紧能简单就简单,也不管什么代码耦合度的问题了.

MVP设计模式

不知道为啥很多人都在用MVP ,具体这东西哪里香 各有各的道理.个人觉得它的优势并不明显.

事件流向
在这里插入图片描述优点: 结构清晰,职责划分清晰,模块间充分解耦,有利于组件的重用.
缺点: 会引入大量的接口,导致项目文件数量激增. 增大代码结构复杂性

MVP 和 MVC 最大的不同,就是 View 和 Model 不相互持有,都通过 Presenter 做中转。View 产生事件,通知给 Presenter,Presenter 中进行逻辑处理后,通知 Model 更新数据,Model 更新数据后,通知数据结构给 Presenter,Presenter 再通知 View 更新界面。

上实例

在这里插入图片描述

就实现一个简单的登录操作.

如果嫌手动写model Presenter contract(MVP管理类) 麻烦可以借助工具去实现,这里推荐一个插件MVP Helper 非常好用
在这里插入图片描述
使用的时候也很简单
在这里插入图片描述
然后直接生成目录
在这里插入图片描述
介绍完这插件该说一下MVP 业务代码的实现了

先从负责数据逻辑的Model层开始说起
(1) 创建用于保存用户信息的实体类 UserBean

public class UserBean {
   

    private String username;
    private String password;
    
    public String getUsername() {
   
        return username;
    }
    public void setUsername(String username) {
   
        this.username = username;
    }

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

(2) 结果回调接口OnLoginListener

public interface OnLoginListener {
   

    //登录成功的回调
    void loginSuccess(UserBean user);
    //登录失败的回调
    void loginFailed();
}

(3) 定义业务接口,在没有使用Contract 管理类的时候,都是把Model 接口单独定义的.但是这里不那样麻烦操作.View Model Presenter 直接定义在loginContract 接口管理类中

public interface loginContract {
   

    interface Model {
   
        void Login(String username, String password, OnLoginListener loginListener);
    }

    interface View {
   

        String getUserName();
        String getPassword();
        void clearUserName();
        void clearPassword();
        void showFail();
        void showLoading();
        void hideLoading();
        void toHomeActivity(UserBean user);
    }

    interface Presenter {
   

        void login();

        void clear();
    }
}

(4) 具体Model的实现类loginModel

public class loginModel implements loginContract.Model {
   

    @Override
    public void Login(final String username, final String password, final OnLoginListener loginListener) {
   
        //模拟网络请求耗时操作
        new Thread() {
   
            @Override
            public void run() {
   
                //模拟了耗时
                try {
   
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
   
                    e.printStackTrace();
                }
                //模拟登录成功 账号 XXX 密码 000
                if ("XXX".equals(username) && "000".equals(password)) {
   
                    UserBean user = new UserBean();
                    user.setUsername(username);
                    user.setPassword(password);
                    loginListener.loginSuccess(user);
                } else {
   
                    loginListener.loginFailed();
                }
            }
        }.start();
    }
}

说完负责数据的Model层 接下来该说说Presenter了,我们知道是Presenter 把View 与Model 相互关联,然后进行逻辑的处理,处理之后在告知View 去更新UI.

注意作为View 与Model 两者之间的 中间人. Presenter必须要能拿到View和Model的实现类

public class loginPresenter implements loginContract.Presenter {
   
    
    private loginContract.View userLoginView;
    private loginModel loginModel;
    private Handler mHandler = new Handler();

    //对应视图页面销毁的标志位,当视图销毁后回调就不需要处理了
    private boolean destroyFlag;

    //Presenter必须要能拿到View和Model的实现类
    public loginPresenter(loginContract.View userLoginView) {
   
        this.userLoginView = userLoginView;
        this.loginModel = new loginModel();
    }


    @Override
    public void login() {
   
        userLoginView.showLoading();
        loginModel.Login(userLoginView.getUserName(), userLoginView.getPassword(), new OnLoginListener() {
   
            @Override
            public void loginSuccess(final UserBean user) {
   
                if (!destroyFlag) {
    //View层销毁后不需要处理的判断
                    //需要在UI线程执行
                    mHandler.post(new Runnable() {
   
                        @Override
                        public void run() {
   
                            userLoginView.toHomeActivity(user);
                            userLoginView.hideLoading();
                        }
                    });
                }
            }

            @Override
            public void loginFailed() {
   
                if (!destroyFlag) {
    //View层销毁后不需要处理的判断
                    //需要在UI线程执行
                    mHandler.post(new Runnable() {
   
                        @Override
                        public void run() {
   
                            userLoginView.showFail();
                            userLoginView.hideLoading();
                        }
                    });
                }
            }
        });
    }

    @Override
    public void clear() {
   
        userLoginView.clearUserName();
        userLoginView.clearPassword();
    }
    
    //解绑视图
    public void detachView() {
   
        destroyFlag = true;
        this.userLoginView = null;
    }
}

最后我们再说一下View 层先看一下代码

public class LoginActivity extends AppCompatActivity implements loginContract.View {
   


    private loginPresenter presenter;
    private EditText etUserName;
    private EditText etPassword;
    private LoadingDialog loadingDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
   
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        presenter = new loginPresenter(this);
        initView();


    }

    private void initView() {
   
        Button btnLogin = findViewById(R.id.btn_login);
        btnLogin.setOnClickListener(new View.OnClickListener() {
   
            @Override
            public void onClick(View v) {
   
                presenter.login();
            }
        });
        Button btnClean = findViewById(R.id.btn_clean);
        btnClean.setOnClickListener(new View.OnClickListener() {
   
            @Override
            public void onClick(View v) {
   
                presenter.clear();
            }
        });
        etUserName = findViewById(R.id.et_user_name);
        etPassword = findViewById(R.id.et_password);
        loadingDialog = new LoadingDialog(LoginActivity.this, "加载中...");

    }


    @Override
    public String getUserName() {
   
        return etUserName.getText().toString();
    }

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

    @Override
    public void clearUserName() {
   
        etUserName.setText("");

    }

    @Override
    public void clearPassword() {
   
        etPassword.setText("");
    }

    @Override
    public void showFail() {
   
        Toast.makeText(this, "登录失败", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showLoading() {
   
        loadingDialog.show();
    }

    @Override
    public void hideLoading() {
   
        loadingDialog.dismiss();
    }

    @Override
    public void toHomeActivity(UserBean user) {
   
        Toast.makeText(this, "跳转到登录成功页面", Toast.LENGTH_SHORT).show();
    }
    
    @Override
    protected void onDestroy() {
   
        super.onDestroy();
        //为了防止内存泄漏,解绑Presenter层对View层的引用
        presenter.detachView();
    }
}

总结一下
MVP设计模式 在activity Fragment 中处理数据更新数据的方式进行解耦,在Presenter 中 View 与 Model 进行逻辑处理. 而数据的处理 在Model 中进行操作. 这样去做结构明了.但是弊端也是有的 目录层级过多,代码量增大.

最近接手的项目 我发现很多人,把Model 层处理数据(网络请求)这部分放在了Presenter 层中进行处理.
比如

public class EditAddressContact {
   
    public interface View extends BaseContact.BaseView {
   
        void showError(String msg);

        void Success();

        void showCityList(List<LianDongBean.ResultBean> result);

        void deleteSuccess();
    }

    public interface presenter {
   
        void AddAddress(int city_id, int county_id, String ua_detail);
        }

这样

public class EditAddressPresenter extends RxPresenter<EditAddressContact.View> implements EditAddressContact.presenter {
   
    @Inject
    public EditAddressPresenter() {
   
    }


    @Override
    public void AddAddress( int city_id, int county_id,String ua_detail) {
   
        OkGo.<LianDongBean>post(Constant.IP + Constant.addaddress)
                .params("token", PreferenceManager.getInstance().getToken())
                .params("city_id", city_id)
                .params("county_id", county_id)
                .params("ua_detail", ua_detail)
                .execute(new JsonCallback<LianDongBean>() {
   
                    @Override
                    protected void onVerifySuccess(Response<LianDongBean> response) {
   
                        if (response.body().getStatus() == 0) {
   
                            view.Success();
                        } else view.showError(response.body().getMsg());
                    }

                    @Override
                    public void onError(Response<LianDongBean> response) {
   
                        super.onError(response);
                        view.showError(handleError(response.getException()));
                    }
                });
    }
    
  }

这种我不能说这种不好,总之一切为了业务方便而定 =_= !

希望可以帮到你

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/2818.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • springsource sts 初使用

    springsource sts 初使用

  • STM32驱动OV7725摄像头颜色识别「建议收藏」

    STM32驱动OV7725摄像头颜色识别「建议收藏」实验目的:使用stm32驱动OV7725摄像头进行图像实时采集,在tft屏幕上实时显示并识别图像中的特定颜色,在颜色的周围画上框。实验现象:我的工程代码链接:http://download.csdn.net/my程序移植自阿莫论坛某位大神的程序。链接:http://www.amobbs.com/thread-5499408-1-1.html?_dsign=85056954实现原理:

  • Java的jar包和war包的异同

    Java的jar包和war包的异同最近思考了一下jar包和war包的异同,发现一篇文章写的非常不错,翻译在此。一、概述本文主要讨论Java中war包和jar包的不同。首先,我们先看不同包的结构,然后对比他们的不同。二、JAR包jar包的文件拓展名为:.jar,包含库,资源和元数据文件。本质上,jar包是一个包含多个.class文件,Java库的和应用的资源文件的压缩包。这是一个简单的jar…

  • 分布式熔断机制_服务器熔断是什么意思啊

    分布式熔断机制_服务器熔断是什么意思啊#服务熔断-“熔断器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器(hystrix)的故障监控,某个异常条件被触发,直接熔断整个服务。向调用方法返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,就保证了服务调用方的线程不会被长时间占用,避免故障在分布式系统中蔓延,乃至雪崩。如果目标服务情况好转则恢复调用。服务熔断是解决服务雪崩的重要手段。#服务熔断图示…

  • linux 大总结[通俗易懂]

    linux 大总结[通俗易懂]1.Linux介绍Linux内核最初只是由芬兰人林纳斯·托瓦兹(LinusTorvalds)在赫尔辛基大学上学时出于个人爱好而编写的。Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。Linux能运行主要的UNIX工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。目前市面上较

  • Android传感器开发与智能设备案例实战_Android移动应用开发

    Android传感器开发与智能设备案例实战_Android移动应用开发学习内容Ø传感器的基本概念ØAndroid中常见的传感器Ø如何在Android中开发传感器应用能力目标Ø了解传感器的基本概念Ø掌握Android中常见的传感器Ø掌握Android环境下如何使用SensorSimulator进行传感器开发Ø熟练掌握加速度传感器的开发步骤Ø熟练掌握方向传感器的开发步骤本章简介Android是一个面向应用程序开发的丰富平台,它除了拥有许多具有吸引力的用户

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号