Android中用到的MVP模式

article/2025/9/23 3:24:21

参考:android架构设计—mvp模式封装

很简单,M:数据, V:界面, P:一个使唤数据(M)和界面(V)干活的大管家。

特点:在P的管理下,P可以直接支配V和M做一些事情。但是V,与M,你可以想象成两者可以是八竿子打不着的关系,生生世世不相见,全靠P在中间呼风唤雨,左手控制着V,右手操纵着M,就这样用一双神来之手将界面调剂成你想要的样子。。。

总结起来看起来很简单的样子哈。

但是,没有一个例子显然是不太有说服力的,MVP到底是个什么样子呢?代码袭来。。。

关于简单登录的案例

首先看下结构:

 

接口:M方面

package com.example.forev.mvpprojectdemo.model;/*** Created by forev on 2018/7/8.* 定义一个model总接口*/public interface IModel {
}

接口: V 方面:

package com.example.forev.mvpprojectdemo.view;/*** Created by forev on 2018/7/8.* 定义一个view总接口*/public interface IView {
}

父类:Presenter方面,表现持有关系。

package com.example.forev.mvpprojectdemo.presenter;import com.example.forev.mvpprojectdemo.model.IModel;
import com.example.forev.mvpprojectdemo.view.IView;import java.lang.ref.WeakReference;/*** Created by forev on 2018/7/8.* 所有presenter的父类,因为presenter会持有View 以及Model部分,所以* 索性就写到总父类里面去吧*/public class PresenterFather {protected IModel mIModel;//此处View个人感觉最好用一个弱引用。protected WeakReference<IView> mViewReference;
}

好,接口相关的关系定义完了,接下来就看看MVP 怎么表现的。

M实际逻辑:

package com.example.forev.mvpprojectdemo.model;import com.example.forev.mvpprojectdemo.model.Lisentener.LoginLisentener;/*** Created by yayali on 2018/7/8.* model 负责的是数据以及业务逻辑*/public class LoginMode implements IModel {//model 负责数据以及业务逻辑。private String mUserName = "yayali";private String mPassWord = "123";public void login(String username, String password, LoginLisentener lisentener) {if (lisentener == null) {return;}if (mUserName.equals(username) && mPassWord.equals(password)){lisentener.onSeccess();} else {lisentener.onFails();}}
}

 

以上可以看出,这个Model里面只有数据和登录的逻辑,就算算出了结果,也用一个回调,回调出去了。写的是相当封闭了。与View无任何关系。

View实际逻辑,首先先写一个根据距离的情景得出的接口。例如总得知道用户在用户名密码编辑框里输入了什么信息吧。这个是必须在View里面获取的。然后,登录成功或者失败总得能给个提示之类的吧。这些具体的提示也是在View里面需要做的。那么写了这几个方法,很明显就是给Presenter来调用的。因为Presenter会作为一个桥梁,来控制View和model之间的联系。从Model那里计算出登录结果,然后控制下面的接口,做相关调用。

package com.example.forev.mvpprojectdemo.view;/*** Created by forev on 2018/7/8.* 写了一个接口继承自IView,这点关系很重要*/public interface ILoginView extends IView {String getUserName();String getPassword();void onLoginSeccess();void onLoginFails();
}

首先写了一个关于View的接口!为什么呢?因为Presenter是个桥接角色,那么它势必会调用Model的业务逻辑,得出结果,然后再操纵其持有的View来进行View上的变更。但是界面呀,毕竟都在Activity里面呆着呢。实际界面变化在Activity里做最合适的。所以就专门写了接口,专门获取用户输入信息,以及界面变化回调。

下面真正的View:

package com.example.forev.mvpprojectdemo.activity;import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;import com.example.forev.mvpprojectdemo.R;
import com.example.forev.mvpprojectdemo.presenter.LoginPresenter;
import com.example.forev.mvpprojectdemo.view.ILoginView;/*** LoginActivity展现了一个界面,尤其是它实现了ILoginView,代表他是MVP中的V*/
public class LoginActivity extends AppCompatActivity implements ILoginView{private EditText mUserNameEdit;private EditText mPasswordEdit;private Button mLoginBtn;private LoginPresenter mPresenter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);setView();setData();}private void setView() {this.mUserNameEdit = findViewById(R.id.login_act_edit_user_name);this.mPasswordEdit = findViewById(R.id.login_act_edit_user_pass);this.mLoginBtn = findViewById(R.id.login_act_btn_login);mLoginBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//隐藏软键盘InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);mPresenter.login();}});}private void setData() {this.mPresenter = new LoginPresenter(this);}@Overridepublic String getUserName() {return mUserNameEdit.getText().toString();}@Overridepublic String getPassword() {return mPasswordEdit.getText().toString();}@Overridepublic void onLoginSeccess() {Toast.makeText(getApplicationContext(), "登陆成功!", Toast.LENGTH_LONG).show();}@Overridepublic void onLoginFails() {Toast.makeText(getApplicationContext(), "登录失败!", Toast.LENGTH_LONG).show();}@Overrideprotected void onDestroy() {super.onDestroy();//记得在销毁的时候断掉引用链,养成良好的习惯this.mPresenter = null;}
}

看吧,界面上没有任何具体的业务逻辑,业务逻辑相关的都交给Presenter去处理了,View顶多就是在回调里面做做界面响应啥的。

Presenter:连接View和Model的桥梁

package com.example.forev.mvpprojectdemo.presenter;import com.example.forev.mvpprojectdemo.model.Lisentener.LoginLisentener;
import com.example.forev.mvpprojectdemo.model.LoginMode;
import com.example.forev.mvpprojectdemo.view.ILoginView;
import com.example.forev.mvpprojectdemo.view.IView;import java.lang.ref.WeakReference;/*** Created by forev on 2018/7/8.*/public class LoginPresenter extends PresenterFather {public  LoginPresenter(ILoginView loginView) {this.mIModel = new LoginMode();this.mViewReference = new WeakReference<IView>(loginView);}public void login() {if (mIModel != null && mViewReference != null && mViewReference.get() != null) {ILoginView loginView = (ILoginView) mViewReference.get();String name = loginView.getUserName();String passWord = loginView.getPassword();loginView = null;//此时LoginListener作为匿名内部类是持有外部类的引用的。((LoginMode)mIModel).login(name, passWord, new LoginLisentener() {@Overridepublic void onSeccess() {if (mViewReference.get() != null) {((ILoginView)mViewReference.get()).onLoginSeccess();}}@Overridepublic void onFails() {if (mViewReference.get() != null) {if (mViewReference.get() != null) {((ILoginView)mViewReference.get()).onLoginFails();}}}});}}
}

这样看Presenter就是根据用户的操作行为来决定怎么调业务逻辑,并且根据业务逻辑的结果再决定怎么调用View。

接下来是Lisentener:

package com.example.forev.mvpprojectdemo.model.Lisentener;/*** Created by forev on 2018/7/8.*/public interface LoginLisentener {void onSeccess();void onFails();
}

 

代码大概就是这样的,重点就是持有关系,以及各自的逻辑要拎得清。。presenter就得 持有View和Model,并且View就是界面展现,Model就是纯业务逻辑。View和Model无任何联系。那么为什么要这么写呢?有什么优点呢?

 

MVP的优缺点

优点: 单一职责, Model, View, Presenter只处理单一逻辑

解耦:Model层的修改和View层的修改互不影响

面向接口编程,依赖抽象:Presenter和View互相持有抽象引用,对外隐藏内部实现细节。

可能存在的问题

Model进行一步操作的时候,获取结果通过Presenter会传到View的时候,出现View引用的空指针异常。

Presenter和View相互持有引用,解除不及时的话容易出现内存泄漏。

 


http://chatgpt.dhexx.cn/article/7sNcQaYV.shtml

相关文章

Android MVP模式 简单易懂的介绍方式

Android MVP Pattern Android MVP 模式1 也不是什么新鲜的东西了&#xff0c;我在自己的项目里也普遍地使用了这个设计模式。当项目越来越庞大、复杂&#xff0c;参与的研发人员越来越多的时候&#xff0c;MVP 模式的优势就充分显示出来了。 导读&#xff1a;MVP模式是MVC模式在…

Android MVP模式详解

一、MVP概述 MVP&#xff0c;全称 Model-View-Presenter&#xff0c;即模型-视图-层现器。 提到MVP&#xff0c;就必须要先介绍一下它的前辈MVC&#xff0c;因为MVP正是基于MVC的基础发展而来的。两个之间的关系也是源远流长。 MVC&#xff0c;全称Model-View-Controller&am…

浅谈安卓MVP模式

本篇博文通过对google官方demo&#xff1a;https://github.com/googlesamples/android-architecture/tree/todo-mvp/的理解&#xff0c;用自己的demo更好的讲解mvp的概念&#xff0c;帮助大家如何针对一个Activity页面去编写针对MVP风格的代码。 一、MVP模式介绍 随着UI创建技…

简单易懂 MVP 模式

Android MVP 模式 [1] 也不是什么新鲜的东西了&#xff0c;我在自己的项目里也普遍地使用了这个设计模式。当项目越来越庞大、复杂&#xff0c;参与的研发人员越来越多的时候&#xff0c;MVP 模式 的优势就充分显示出来了。 MVP 模式是 MVC 模式在 Android 上的一种变体&#…

深入浅出——MVP模式

由于公司里的架构模式用到MVP&#xff0c;觉得自己还不够熟悉&#xff0c;决定在此理一理&#xff0c;并给大家一起总结下。 一 MVP模式介绍 MVP全称Model View Presenter。 MVP能够有效的降低View的复杂性&#xff0c;避免业务逻辑被塞进View中&#xff0c;防止View的代码变…

MVP模式简单讲解,通俗易懂

了解 MVP 和 MVC 的区别 https://baike.baidu.com/item/MVP/3714550?fraladdin 什么是MVP&#xff1a; MVP 是 MVC 的变种&#xff0c;其实是一种升级。要说 MVP 就要说说 MVC&#xff0c;在 MVC 中 Activity 其实是 View层级&#xff0c;但是通常在使用中 Activity即是View…

MVP框架模式

一、基本概念 MVP是Model-View-Presenter的简称&#xff0c;即模型-视图-表现层的缩写。MVP是由MVC模式进化而来的&#xff0c;MVP改进了MVC中的控制器过于臃肿的问题。 与MVC一样&#xff0c;MVP将应用程序的数据处理、数据显示和逻辑控制分开&#xff0c;用一种业务逻辑、数…

分析几个面试题:==和===;绑定事件;正则表达式

今天也是我学后端的朋友给我发了三个前端的面试题&#xff0c;这里我们试着分析一波。 目录 1、和的含义是什么&#xff0c;又有什么区别呢&#xff1f; &#xff08;1&#xff09;赋值&#xff1a; &#xff08;2&#xff09;相同&#xff1a; &#xff08;3&#xff09;…

前端面经总结

HTML及浏览器 对栅栏布局的理解 栅格化布局中的元素&#xff1a;column列&#xff0c;row行&#xff0c;gutter列之间的距离&#xff0c;container容器 栅格是否可以嵌套 canvas和svg的区别 SVG&#xff1a; SVG 是一种使用 XML 描述 2D 图形的语言。 在 SVG 中&#xff0c;…

前端深入学习

但是面试中必考的点且占比非常大的有前端基础和算法。 决定你是否能拿sp offer&#xff08;高薪offer&#xff09;以及是否进名企的是项目和算法。 absolute 生成绝对定位的元素&#xff0c;相对于 static 定位以外的第一个父元素进行定位。 元素的位置通过 “left”, “to…

web前端常用词汇

html中的单词 Network [netwɜːk] 网络 General [dʒen(ə)r(ə)l] 一般的&#xff0c;大体的 Request [rɪkwest] 请求 Response [rɪspɒns] 响应 Headers [hedəz] 标题 HyperText [haɪpətekst] 超文本 Transfer [trnsfɝ] 传递 Protocol [prəʊtə…

前端html、css、JavaScript---硬核知识汇总

前端HTML篇 硬核&#xff01;一篇文章教你阅遍html。 声明&#xff1a;本篇文章只是一个刚开始学习后端开发的菜鸟汇总完成的 JavaWeb学习前导html篇&#xff0c;所以专业性肯定不如前端人员&#xff0c;但用于学习后端开发足够了&#xff0c;刚接触html的童鞋拿来快速了解ht…

前端面试题总结(转载)

DOM结构 —— 两个节点之间可能存在哪些关系以及如何在节点之间任意移动1.DOM中两个节点存在的关系无非3种&#xff1a;1.1.包含与被包含,IE率先引入的contains()方法可检测&#xff0c;例 A.contains(B)&#xff0c;即检查节点B是否是节点A的子节点&#xff0c;返回布尔值&…

前端三件套知识点

html 常用插件 文件比较 常用快捷键 ctrl f 查找当前页面的内容 !后按table 或者 html:5 代码模板快捷键 altb调试快捷键 ctrlk ctrlt改颜色主题 altshifta注释快捷键 html基础概念 一、 WEB标准的概念及组成 WEB标准不是某一个标准&#xff0c;而是一系列标准的集合。 …

php前端搜索功能,JavaScript实现前端实时搜索功能的代码分享(图)

这篇文章主要为大家详细介绍了JavaScript实现前端实时搜索功能&#xff0c;具有一定的参考价值&#xff0c;感兴趣的小伙伴们可以参考一下 大部分页面都具备搜索功能。而作为前端&#xff0c;我们的目的只是将用户输入的内容返回给后台而后呈现反馈数据给用户&#xff0c;具体实…

前端实时搜索功能

** 大部分页面都具备搜索功能。而作为前端&#xff0c;我们的目的只是将用户输入的内容返回给后台而后呈现反馈数据给用户&#xff0c;具体实现如下&#xff1a; ** 1.基本布局&#xff1a; <div class"searcher"><p class"searcher-main">…

适合后端开发人员的html笔记

1html 锚点 <a href"#bottom">跳转到底部</a> <div class"aa"></div> <a href"#" id"bottom">跳转到顶部</a> img 图片标签 h1:一级标题块级元素其他的都是行内元素 img同时具备行内元素和块级…

【JavaScript】 一万字 JavaScript 笔记(详细讲解 + 代码演示 + 图解)

文章目录 变量 变量声明的提升数据类型Typeof运算符数据类型转换 表达式与运算符 隐式类型转换toFixed(a)方法保留a位小数关系运算符短路求值流程控制语句 数组函数DOMBOM面向对象 变量 一个变量只定义但没有赋初值&#xff0c;默认值是 undefined定义变量时必须写var&a…

前端面试 汇总整理

-----------------------------------------html css-------------------------------------------- 一.回流与重绘 回流一定引起重绘&#xff0c;重绘不一定回流 1.浏览器渲染机制 1&#xff09;浏览器采用流式布局。 2&#xff09;浏览器将html解析成DOM&#xff0c;css解析成…

JavaWeb——后端开发必备的JavaScript知识

JS学习 1.什么是JavaScript&#xff0c;有什么用&#xff1f; 答&#xff1a;JavaScript是网景公司发明的&#xff0c;运行在浏览器上的脚本语言&#xff0c;简称JS。 补充&#xff1a;网景公司现在没了&#xff0c;被美国在线收购了。 2.在HTML中嵌入JavaScript代码的三种方…