Android MVP浅谈
2016-11-11 17:26
183 查看
随着技术的发展,Activity(View) 做的事情越来越多,动辄几百上千行的代码使得 Activity 越来越臃肿。为了更好的划分视图(View)和模型(Model)之间的职责,让 View 只处理数据的展示和用户的交互,把数据的处理交由 Model 处理。 这种模式便是MVP。
我们都知道Android中比较常用的模式是MVC模式,那么MVC模式是什么呢?它和MVP模式有什么区别呢?
一、概述。
1.MVC模式;
先看MVC模式的结构图,
MVC模式的结构分为三部分,Model、View、Controller。
(1).Model:业务逻辑和实体模型;
(2).View:应用的UI界面,也就是布局文件;
(3).Controller:负责处理用户事件和视图部分的展示。在Android中,它可能是Activity或者Fragment类;
在Android开发中使用MVC模式,View是布局文件,它的内容只是布局,而Controller即Activity或者Fragment类或者其他类,既要处理View又要处理数据,因此View视图和[b]Controller控制器并不是完全分离的,并且造成了Controller的代码量非常大,还有可能出现好多重复代码,单元测试也不好测试等等。[/b]
三个模块之间都可以通信,但是都是单向的。
a).View传送指令到Controller;
b).[b]Controller完成业务逻辑后,要求Model改变状态;[/b]
c).Model将新的数据发送给View,用户得到反馈。
2.MVP模式;
下面是MVP模式的结构图,
MVP模式的结构也分为三部分,Model、View、Presenter。
(1).Model: 处理数据的加载或者存储,比如从网络或本地获取数据等;
(2).View:用户交互和视图显示,在Android中,它可能是Activity或者Fragment类;
(3).Presenter: 负责完成View于Model间的逻辑和交互,是模型与视图之间的桥梁,将模型与视图分离开来。
使用MVP模式,当有交互时,调用Presenter里的对应方法。 Presenter 负责完成View于Model间的交互,从Model里取数据,返回给View处理好的数据。 View不直接与Model交互。
模块之间的通信是相互的,但是禁止View和Model之间通信。
a).[b]View和Model之间通信必须通过Presenter来进行传达;[/b]
b).所有的业务逻辑都放在[b][b]Presenter(这样会比较臃肿,具体设计时,要注意瘦身);[/b][/b]
c).View只负责展示数据,由[b]Presenter决定从Model中拿什么数据。[/b]
3.MVP模式的好处;
View不直接与Model交互 ,而是通过与Presenter交互来与Model间接交互 Presenter与View的交互是通过接口来进行的,更有利于添加单元测试 通常View与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑
这样分层的好处就是大大减少了Model与View层之间的耦合度。一方面可以使得View层和Model层单独开发与测试,互不依赖。另一方面Model层可以封装复用,可以极大的减少代码量。当然,MVP还有其他的一些优点,这里不再赘述。下面看下MVP模式在具体项目中的使用。
PS:
1.M(Model),模型:表示数据模型和业务逻辑(business logic)。
model层主要负责:
· 从网络,数据库,文件,传感器,第三方等数据源读写数据。
· 对外部的数据类型进行解析转换为APP内部数据交由上层处理。
· 对数据的临时存储,管理,协调上层数据请求。
2.V(View),视图:将数据呈现给用户。一般的视图都只是包含用户界面(UI),而不包含界面逻辑。
view 层主要负责:
· 提供UI交互
· 在presenter的控制下修改UI。
· 将业务事件交由presenter处理。
注意: View层不存储数据,不与Model层交互。
在Android中View层一般是Activity、Fragment、View(控件)、ViewGroup(布局等)等。
3.P(Presenter),
作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。Presenter包含了根据用户在视图中的行为去更新模型的逻辑。视图仅仅只是将用户的行为告知Presenter,而Presenter负责从视图中取得数据然后发送给模型。
4.MVP模式具体的执行过程。
View与Model并不直接交互,而是使用Presenter作为View与Model之间的桥梁。其中Presenter中同时持有Viwe层以及Model层的Interface的引用,而View层持有Presenter层Interface的引用。当View层某个界面需要展示某些数据的时候,首先会调用Presenter层的某个接口,然后Presenter层会调用Model层请求数据,当Model层数据加载成功之后会调用Presenter层的回调方法通知Presenter层数据加载完毕,最后Presenter层再调用View层的接口将加载后的数据展示给用户。
二、项目示例。
实现一个登录实例。
先看项目的整体结构,
项目中使用了OkHttp访问网络(有关OkHttp,详情请看Android OkHttp(二)实战),这个项目还需要运行一个后台接口服务,用于登录(有关接口开发,详情请看
SpringMVC 开发接口和 java web开发(二) 接口开发),此处就不再详说了。下面看看具体实现。
1.首先创建一个实体对象,这个肯定有,
2.Model层;
需要定义一个接口,有一个登录方法,
3.View层;
需要定义View层的接口。View层具体需要哪些接口,这个要根据实际情况来定义,这里借用鸿洋博文中的原文:
例如,异步操作的话,友好提示,要显示进度条、关闭进度条,
显示提示信息,
综上,该View的接口有如下这些方法,
4.Presenter层,
实现Presenter功能,可以定义一个接口,也可以定义一个类。Presenter要实现的功能是直接调用Model中实现方法,并且要向View提供方法。(这里我先定义了一个接口,然后去实现该接口),
好了,以上就是使用MVP模式实现一个登陆功能。下面运行程序看看效果。
首先这张截图是数据库中的表中的数据,有两条数据,
下面是App的运行截图,
这两种截图分别是,密码正确和密码错误的截图。
三、MVP模式小结。
在MVP模式里通常包含4个要素:
(1) View :负责绘制UI元素、与用户进行交互(在Android中体现为Activity);
(2) View interface :需要View实现的接口,View通过View interface与Presenter进行交互,降低耦合,方便进行单元测试;
(3) Model :负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合);
(4) Presenter :作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。
至此,以上就是有关MVP模式的一点浅谈,本文参考了鸿洋的MVP博客。目前也有一些观点是,Activity是一个上帝类,其实不适合作为View,所以有些MVP方案将Activity作为Presenter,最主要在于他的生命周期牵扯太多逻辑处理业务,这些由Presenter负责的话情况可以改善很多。所以,MVP模式的实现方式是多样的,在此也呼吁更多人来关注该模式!
Demo下载链接!
PS:
1).推荐一个Android Studio插件,方便快捷使用MVP模式开发,插件名为MVPHelper,直接可以在Android Studio插件管理中搜索,当然也可以先下载,然后安装。
2). MVVM框架(Model-View-ViewModel)
1.MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致。
2.唯一的区别就是,View和ViewModel之间是“双向绑定“的,View的变动,自动反映在 ViewModel,反之亦然。
3.MVVM可以降低UI显示与后端逻辑代码的耦合度,即更换界面时,只需要修改很少的逻辑代码就可以实现,甚至不用修改。
2
2
3/
sd
我们都知道Android中比较常用的模式是MVC模式,那么MVC模式是什么呢?它和MVP模式有什么区别呢?
一、概述。
1.MVC模式;
先看MVC模式的结构图,
MVC模式的结构分为三部分,Model、View、Controller。
(1).Model:业务逻辑和实体模型;
(2).View:应用的UI界面,也就是布局文件;
(3).Controller:负责处理用户事件和视图部分的展示。在Android中,它可能是Activity或者Fragment类;
在Android开发中使用MVC模式,View是布局文件,它的内容只是布局,而Controller即Activity或者Fragment类或者其他类,既要处理View又要处理数据,因此View视图和[b]Controller控制器并不是完全分离的,并且造成了Controller的代码量非常大,还有可能出现好多重复代码,单元测试也不好测试等等。[/b]
三个模块之间都可以通信,但是都是单向的。
a).View传送指令到Controller;
b).[b]Controller完成业务逻辑后,要求Model改变状态;[/b]
c).Model将新的数据发送给View,用户得到反馈。
2.MVP模式;
下面是MVP模式的结构图,
MVP模式的结构也分为三部分,Model、View、Presenter。
(1).Model: 处理数据的加载或者存储,比如从网络或本地获取数据等;
(2).View:用户交互和视图显示,在Android中,它可能是Activity或者Fragment类;
(3).Presenter: 负责完成View于Model间的逻辑和交互,是模型与视图之间的桥梁,将模型与视图分离开来。
使用MVP模式,当有交互时,调用Presenter里的对应方法。 Presenter 负责完成View于Model间的交互,从Model里取数据,返回给View处理好的数据。 View不直接与Model交互。
模块之间的通信是相互的,但是禁止View和Model之间通信。
a).[b]View和Model之间通信必须通过Presenter来进行传达;[/b]
b).所有的业务逻辑都放在[b][b]Presenter(这样会比较臃肿,具体设计时,要注意瘦身);[/b][/b]
c).View只负责展示数据,由[b]Presenter决定从Model中拿什么数据。[/b]
3.MVP模式的好处;
View不直接与Model交互 ,而是通过与Presenter交互来与Model间接交互 Presenter与View的交互是通过接口来进行的,更有利于添加单元测试 通常View与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑
这样分层的好处就是大大减少了Model与View层之间的耦合度。一方面可以使得View层和Model层单独开发与测试,互不依赖。另一方面Model层可以封装复用,可以极大的减少代码量。当然,MVP还有其他的一些优点,这里不再赘述。下面看下MVP模式在具体项目中的使用。
PS:
1.M(Model),模型:表示数据模型和业务逻辑(business logic)。
model层主要负责:
· 从网络,数据库,文件,传感器,第三方等数据源读写数据。
· 对外部的数据类型进行解析转换为APP内部数据交由上层处理。
· 对数据的临时存储,管理,协调上层数据请求。
2.V(View),视图:将数据呈现给用户。一般的视图都只是包含用户界面(UI),而不包含界面逻辑。
view 层主要负责:
· 提供UI交互
· 在presenter的控制下修改UI。
· 将业务事件交由presenter处理。
注意: View层不存储数据,不与Model层交互。
在Android中View层一般是Activity、Fragment、View(控件)、ViewGroup(布局等)等。
3.P(Presenter),
作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。Presenter包含了根据用户在视图中的行为去更新模型的逻辑。视图仅仅只是将用户的行为告知Presenter,而Presenter负责从视图中取得数据然后发送给模型。
4.MVP模式具体的执行过程。
View与Model并不直接交互,而是使用Presenter作为View与Model之间的桥梁。其中Presenter中同时持有Viwe层以及Model层的Interface的引用,而View层持有Presenter层Interface的引用。当View层某个界面需要展示某些数据的时候,首先会调用Presenter层的某个接口,然后Presenter层会调用Model层请求数据,当Model层数据加载成功之后会调用Presenter层的回调方法通知Presenter层数据加载完毕,最后Presenter层再调用View层的接口将加载后的数据展示给用户。
二、项目示例。
实现一个登录实例。
先看项目的整体结构,
项目中使用了OkHttp访问网络(有关OkHttp,详情请看Android OkHttp(二)实战),这个项目还需要运行一个后台接口服务,用于登录(有关接口开发,详情请看
SpringMVC 开发接口和 java web开发(二) 接口开发),此处就不再详说了。下面看看具体实现。
1.首先创建一个实体对象,这个肯定有,
public class User implements Serializable { public int id; public String name; public int age; public int sex; public int mobile; public int getMobile() { return mobile; } public void setMobile(int mobile) { this.mobile = mobile; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getSex() { return sex; } public void setSex(int sex) { this.sex = sex; } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", age=" + age + ", sex=" + sex + "]"; } }User类定义了用户的一些属性,很简单,不多说了。
2.Model层;
需要定义一个接口,有一个登录方法,
public interface IUserLoginModel { public void login(String userName, String passWord, CallBackListener callBackListener); }然后实现该接口,
public class UserLoginModelImpl implements IUserLoginModel { @Override public void login(String userName, String passWord, final CallBackListener callBackListener) { //接口返回的json TypeToken<EntityResponse<User>> typeToken = new TypeToken<EntityResponse<User>>() { }; Map<String, String> params=new HashMap<>(); params.put("name",userName); params.put("pws",passWord); OkHttpUtils.getInstance().postAsyn(Constant.LOGIN_URL, params, typeToken, new BaseResponseCallback<EntityResponse<User>>() { @Override public void onCompleted(final Throwable e, EntityResponse<User> result) { if (e != null) { callBackListener.fail(e.getMessage()); } else { User user = result.getObject(); callBackListener.success("登录成功", user); } } }); } }这个类就是具体完成功能的类。目前这个类使用Okhttp实现了登录方法,登录成功返回登录用户的信息,登录失败返回错误提示。
3.View层;
需要定义View层的接口。View层具体需要哪些接口,这个要根据实际情况来定义,这里借用鸿洋博文中的原文:
对于View的接口,去观察功能上的操作,然后考虑: 该操作需要什么?(getUserName, getPassword) 该操作的结果,对应的反馈?(toMainActivity, showFailedError) 该操作过程中对应的友好的交互?(showLoading, hideLoading)
例如,异步操作的话,友好提示,要显示进度条、关闭进度条,
public void showProgressDialog(); public void stopProgressDialog();登录成功、失败后的处理,
public void userLoginSuccess(User user); public void userLoginFail(String result);
显示提示信息,
public void showMessage(String msg);
综上,该View的接口有如下这些方法,
public interface IUserLoginView { public void showProgressDialog(); public void stopProgressDialog(); public void userLoginSuccess(User user); public void userLoginFail(String result); public void showMessage(String msg); }下面就是View的实现类,即Activity,此处是LoginActivity,
public class LoginActivity extends Activity implements IUserLoginView { private EditText etUserName; private EditText etPassWord; private Button btnLogin; private UserLoginPresenterImpl userLoginPresenter; private ProgressDialog progressDialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.login_activity); etUserName = (EditText) findViewById(R.id.et_userName); etPassWord = (EditText) findViewById(R.id.et_passWord); btnLogin = (Button) findViewById(R.id.btn_login); userLoginPresenter = new UserLoginPresenterImpl(this); btnLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { userLoginPresenter.login(etUserName.getText().toString(), etPassWord.getText().toString()); } }); } @Override public void showProgressDialog() { if (progressDialog == null) { progressDialog = new ProgressDialog(this); progressDialog.setTitle("提示"); progressDialog.setMessage("正在登录中..."); } progressDialog.show(); } @Override public void stopProgressDialog() { if (progressDialog != null) { progressDialog.dismiss(); } } @Override public void userLoginSuccess(User user) { showMessage("登录成功!"); stopProgressDialog(); final StringBuffer sb = new StringBuffer(); sb.append("姓名:" + user.getName() + ", 年龄" + user.getAge() + ", 电话" + user.getMobile()).append("\n"); showMessage(sb.toString()); } @Override public void userLoginFail(String result) { stopProgressDialog(); showMessage(result); } @Override public void showMessage(String msg) { ToastUtils.showToast(this, msg); } }点击按钮时,调用Presenter的登录方法。可以看出LoginActivity的代码是比较整洁,简单的。最后再看看Presenter的实现。(更新UI记得要在主线程中哦!即使是显示Toast,也要在主线程中显示,否则会出错哦!)
4.Presenter层,
实现Presenter功能,可以定义一个接口,也可以定义一个类。Presenter要实现的功能是直接调用Model中实现方法,并且要向View提供方法。(这里我先定义了一个接口,然后去实现该接口),
public interface IUserLoginPresenter { public void login(String userName, String passWord); }接着实现该接口,
public class UserLoginPresenterImpl implements IUserLoginPresenter { private UserLoginModelImpl userLoginModel; private IUserLoginView mIUserLoginView; private Handler myHandler = new Handler(Looper.getMainLooper()); public UserLoginPresenterImpl(IUserLoginView userLoginView) { this.mIUserLoginView = userLoginView; userLoginModel=new UserLoginModelImpl(); } @Override public void login(String userName, String passWord) { if (TextUtils.isEmpty(userName)) { mIUserLoginView.showMessage("用户名不能为空!"); return; } if (TextUtils.isEmpty(passWord)) { mIUserLoginView.showMessage("密码不能为空!"); return; } mIUserLoginView.showProgressDialog(); userLoginModel.login(userName, passWord, new CallBackListener<User>() { @Override public void success(String result, final User user) { if (!TextUtils.isEmpty(result)) { myHandler.post(new Runnable() { @Override public void run() { mIUserLoginView.userLoginSuccess(user); } }); } } @Override public void fail(final String result) { if (!TextUtils.isEmpty(result)) { myHandler.post(new Runnable() { @Override public void run() { mIUserLoginView.userLoginFail(result); } }); } } }); } }该类调用了Model层提供的登录方法。
好了,以上就是使用MVP模式实现一个登陆功能。下面运行程序看看效果。
首先这张截图是数据库中的表中的数据,有两条数据,
下面是App的运行截图,
这两种截图分别是,密码正确和密码错误的截图。
三、MVP模式小结。
在MVP模式里通常包含4个要素:
(1) View :负责绘制UI元素、与用户进行交互(在Android中体现为Activity);
(2) View interface :需要View实现的接口,View通过View interface与Presenter进行交互,降低耦合,方便进行单元测试;
(3) Model :负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合);
(4) Presenter :作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。
至此,以上就是有关MVP模式的一点浅谈,本文参考了鸿洋的MVP博客。目前也有一些观点是,Activity是一个上帝类,其实不适合作为View,所以有些MVP方案将Activity作为Presenter,最主要在于他的生命周期牵扯太多逻辑处理业务,这些由Presenter负责的话情况可以改善很多。所以,MVP模式的实现方式是多样的,在此也呼吁更多人来关注该模式!
Demo下载链接!
PS:
1).推荐一个Android Studio插件,方便快捷使用MVP模式开发,插件名为MVPHelper,直接可以在Android Studio插件管理中搜索,当然也可以先下载,然后安装。
2). MVVM框架(Model-View-ViewModel)
1.MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致。
2.唯一的区别就是,View和ViewModel之间是“双向绑定“的,View的变动,自动反映在 ViewModel,反之亦然。
3.MVVM可以降低UI显示与后端逻辑代码的耦合度,即更换界面时,只需要修改很少的逻辑代码就可以实现,甚至不用修改。
2
2
3/
sd
相关文章推荐
- 浅谈MVP实现Android应用层开发
- 浅谈 MVP in Android
- Android学习之浅谈对MVC模式和MVP模式的理解
- 浅谈MVP in Android
- Android设计模式之浅谈MVP
- 浅谈MVP实现Android应用层开发
- 浅谈Android中MVP模式与MVC模式的区别
- Android设计模式之浅谈MVP
- 浅谈Android MVP设计模式(简单结合RxJava+Retrofit)
- 浅谈Android中MVP模式用于实际项目中的问题与优化
- 浅谈MVP In Android
- 浅谈 MVP in Android
- 浅谈MVP实现Android应用层开发
- 浅谈android开发中的MVP模式
- Android设计模式之浅谈MVP
- 浅谈 MVP in Android
- 浅谈 MVP in Android
- 浅谈Android开发中内存泄露与优化与框架模式之MVC与MVP
- 浅谈Android中的MVC与MVP模式
- 浅谈Android中的MVP