简单聊一聊Android中MVP开发
来源:互联网 发布:金蝶k3数据交换平台 编辑:程序博客网 时间:2024/06/05 23:52
前言
新年新气象,Blin祝大家在新的一年中事业一帆风顺!好了,年是过完了,不知道小伙伴们是否也都已经到了工作岗位,开始新的一年的征程了呢。废话不多说,我们这次主要是以聊一聊为主,简单讲一讲在我们的Android开发中被大家普遍接受的MVP开发,上干货!
简介
对于MVP,全称是Model View Presenter,相比对这东西都有点耳熟能详的感觉有木有,现在很多项目都是用这个开发模式进行公司或个性项目的开发。其实我在第一次了解MVP的时候,感觉就是东西不错,但是烦。那么MVP到底是什么呢?其实也很简单,就是由我们以往一直使用的MVC演化而来,如果你做过公司的大型项目,想必你也无时无刻不在抱怨,一个项目主页面的Activity少则数千行,多则上万行。当然此篇博文更多的是作为一篇日记一样以及本人的一些想法,如果有什么问题的话也请大牛们指正,一起相互学习。
和MVC的区别
这一点的话必须要搞清楚,为什么会有MVP,归根结底就是为了弥补一些MVC的缺点。它们的基本思想肯定是有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过 Controller。
区别如下图:(引用hongyang大神博文的的图片)
个人总结MVP的话其实用一句话来说明就可以了:大型项目,多人开发MVP必定是未来的趋势。如果是单人或者两个人开发的
话,个人觉得你用MVC也是很不错的,毕竟MVP开发成本太高,至少从类上来讲,那多出的类的个数差不多是一倍之差啊。
那说了这么多没用的,我们也来总结一下MVP的优点吧:
1、模型与视图完全分离,我们可以修改视图而不影响模型
2、可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter内部
3、我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型
的变化频繁。
4、如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)
Login MVP Demo
还有其他的一些概念性的东西也就不多说了,我们直接看Demo然后来真正的熟悉一下到底MVP开发模式是如何应用在实际的项
目中的,我这里以一个简单的一个登陆系统为例子来说一下吧。(本来想用自己个人项目的【比比账号通】的登录接口,但是为了
简单化,主要是了解MVP,所以我们就模拟一下吧)
首先来看一下我们要实现的效果:
这个功能如果大家用MVC来写,那肯定是分分钟的事情,但是如果是用MVP,可能就像我第一次自己写的的时候还真有点不好
写,下图是小项目的结构:
那么我们怎么来运用MVP呢,顺着我自己的思路一步一步来,首先既然是一个登陆系统,那么必然存在用户这个bean类,我们先
把bean类写好,如下:
package com.yiguo.blin.loginmvpdemo.bean;
/** * Created by zhaocheng on 2016/2/18. */public class User { private String telephone; private String password; public String getTelephone() { return telephone; } public void setTelephone(String telephone) { this.telephone = telephone; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; }}
(一)Modle
最简单的Bean写好,那么我们就要开始摸索这个MVP中的Modlel.
这个小项目就一个小功能,那就是登陆,那么是谁来用这个功能呢,很显然,不用多讲,新建IUser。如下:
package com.yiguo.blin.loginmvpdemo.model;/** * Created by zhaocheng on 2016/2/18. */public interface IUser { void login(String telephone,String password,OnLoginListener loginListener);}
当然我这是直接写完后再把代码贴上来,给大家理一遍的,登录功能嘛,肯定要账号密码的,那么为什么还要一个借口呢,也很简
单,就是为了处理登录后,回调接口,用来处理登录后要处理的事情,对吧。应该不难理解的。
然后创建UserModel,去实现上面的接口,代码如下:
package com.yiguo.blin.loginmvpdemo.model;import com.yiguo.blin.loginmvpdemo.bean.User;/** * Created by zhaocheng on 2016/2/22. */public class UserModel implements IUser { @Override public void login(final String telephone, final String password, final OnLoginListener loginListener) { //这边我们需要模拟一个耗时操作 new Thread() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //然后这边模拟登录成功 if ("blin".equals(telephone) && "000000".equals(password)){ User user = new User(); user.setTelephone(telephone); user.setPassword(password); loginListener.loginSuccess(user); }else{ loginListener.loginFailed(); } } }.start(); }}
上面的就是主要的Model了,我这边就是模拟了一下登录请求,用子线程睡眠模拟。不要吐槽,我们的重点不是在这里(。・∀・)ノ゙。
然后忘记了一个,上面的接口我们还没有定义呢,当然实际开发你肯定会先写这个回调接口的,不然看上IUser报错也是不爽,尤其是我这种有强迫症的人。
package com.yiguo.blin.loginmvpdemo.model;import com.yiguo.blin.loginmvpdemo.bean.User;/** * Created by zhaocheng on 2016/2/18. */public interface OnLoginListener { void loginFailed(); void loginSuccess(User user);}
Model其实就是这么简单的,和以往的写法也没什么区别是吧。
(二)View
接下来我们来看看View,其实呢没说白了,我们做这么多就是为了解耦,那么和View相关的事件有什么呢,以往可能直接在
Activity中写的和View有关的事件在MVP中都会通过接口,然后Activity再去实现。所以,刚开始不能理解,或者摸不着头脑的,
可以先按照以往的写法,然后再进去解耦。当然这样的方法肯定是违背了我们用MVP的初衷的。
我也就直接贴出干活了,大家自己看下也应该明白,就是把一些以往直接写在Activity中的和View有关的操作通过接口一一分开封装起来啦。
package com.yiguo.blin.loginmvpdemo.view;
import com.yiguo.blin.loginmvpdemo.bean.User;
/** * Created by zhaocheng on 2016/2/22. */public interface IUserLogin { String getTelephone(); String getPassword(); void showLoading(); void hideLoading(); void toLoginFailedView(); void toLoginSuccessView(User user);}
然后就是用Activity去实现啊这些方法了呗。
package com.yiguo.blin.loginmvpdemo.view;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.Toast;import com.yiguo.blin.loginmvpdemo.R;import com.yiguo.blin.loginmvpdemo.bean.User;import com.yiguo.blin.loginmvpdemo.presenter.UserLoginPresenter;public class MainActivity extends AppCompatActivity implements IUserLogin{ private Button btn_login; private EditText et_account,et_password; private UserLoginPresenter userLoginPresenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); initEvent(); } private void init(){ btn_login = (Button) findViewById(R.id.btn_login); et_account = (EditText) findViewById(R.id.et_account); et_password = (EditText) findViewById(R.id.et_password); userLoginPresenter = new UserLoginPresenter(this); } private void initEvent(){ btn_login.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { userLoginPresenter.login(); } }); } @Override public String getTelephone() { return et_account.getText().toString(); } @Override public String getPassword() { return et_password.getText().toString(); } @Override public void showLoading() { btn_login.setText("正在登陆。。。"); } @Override public void hideLoading() { btn_login.setText("登录"); } @Override public void toLoginFailedView() { Toast.makeText(this,"账号或密码错误!",Toast.LENGTH_SHORT).show(); } @Override public void toLoginSuccessView(User user) { Toast.makeText(this,"欢迎"+user.getTelephone()+"正在跳转。。。",Toast.LENGTH_SHORT).show(); }}
当然我们的Presenter还没写,我就直接把整个Avtivity贴出来了。。。有点不妥。我们从上面的点击事件中可以看到,点击以后就
是通过userLoginPresenter去调用登录方法了。所以真的在Activity中的逻辑你都看不到了,全都的业务都有Presenter接手。
(三)Presenter
最后就是我们的Presenter了,他的出现就是为了帮助我们处理Model和View之间的数据交互啦,基本上所有的业务也都在这里了。
package com.yiguo.blin.loginmvpdemo.presenter;import android.os.Handler;import com.yiguo.blin.loginmvpdemo.bean.User;import com.yiguo.blin.loginmvpdemo.model.OnLoginListener;import com.yiguo.blin.loginmvpdemo.model.UserModel;import com.yiguo.blin.loginmvpdemo.view.IUserLogin;/** * Created by zhaocheng on 2016/2/22. */public class UserLoginPresenter { private UserModel userModel; private IUserLogin userView; public User user; private Handler handler = new Handler(); public UserLoginPresenter(IUserLogin userView){ userModel = new UserModel(); this.userView = userView; this.user = new User(); } public void login(){ userView.showLoading(); userModel.login(userView.getTelephone().toString(), userView.getPassword().toString(), new OnLoginListener() { @Override public void loginFailed() { //注意这里,我们是模拟了延迟操作,而且是在子线程,所以这里要调用改变UI的操作必须回到主线程。 handler.post(new Runnable() { @Override public void run() { userView.toLoginFailedView(); userView.hideLoading(); } }); } @Override public void loginSuccess(final User user) { //同上 handler.post(new Runnable() { @Override public void run() { userView.toLoginSuccessView(user); userView.hideLoading(); } }); } }); }}
业务就是一个登录,对的,那就来一个登录的方法接口呗。用我们最简单的逻辑去想一下,当点击登录以后,然后调用登录方法,
那么在Presenter中肯定有我们在Activity中实现的接口对象,还有就是Model对象。还有就是那个回调接口直接在这里被初始化
传入,然后处理登录后处理相应的操作,就是因为接口对象的存在,才使得Activity中的方法在Presenter中被轻松的调用到。
总的来说,对于刚入门的,可能这几个接口就把你搞晕了,的确是有点绕,比直接使用我们习惯的MVC的确要夺走一点路子。但是这些东西也是值得的,试想,本来一个页面中的东西可能用MVC开发,等到大家都签入的时候,各种冲突,然而如果是用MVP
开发的话,大家同时使用的就那个Activity,就是每个人多了一些业务接口呗。
大家刚接触的绝对不要慌,这个东西其实昨天和我朋友两个人也聊了很多,的确发现很多年以避免的问题,尤其是类爆炸,或者是当业务逻辑比较复杂时,自己都会搞晕,或者说为了写一个简单的功能浪费了2倍的时间等等,但是作为一个Android的 不管以后是不是会成为主流,但是相比还是要了解一下的,对吧。
PS
好啦,这是2016的第一篇,今天又是元宵,祝大家节日快乐哈~
代码下载地址:
Android MVP 下载
- 简单聊一聊Android中MVP开发
- Android开发中 MVP模式
- Android 开发模式MVP模式简单运用
- android开发MVP模式的简单应用
- Android中使用MVP的简单封装
- Android中MVP模式的简单实现
- Android中Mvp模式的简单示例
- Android中MVP模式的简单应用
- Android开发中MVP模式浅析
- Android开发中使用MVP模式
- 在Android开发中使用MVP模式
- 在Android开发中使用MVP模式
- 在Android开发中使用MVP模式
- 在Android开发中使用MVP模式
- 在Android开发中使用MVP模式
- 在Android开发中使用MVP模式
- Android开发中使用MVP模式
- Android 开发中MVP框架的应用
- 翻翻git之---好看的卡片切换库 Swipecards
- 2.4g遥控发射机接收机基本流程
- 01背包动态规划
- Android通过Movie展示Gif格式图片
- jQuery 插入元素时绑定事件 或 已加载的html绑定事件
- 简单聊一聊Android中MVP开发
- Python之enumerate
- Codevs_P1237 餐巾问题(线性规划与网络流24题+最小费用最大流)
- Linux下MySQL数据库常用基本操作 一
- EPON、10GEPON更适合FTTH规模应用
- 自定义SeekBar
- 快速认识不一样的ABBYY FineReader Pro for Mac(上)
- DIV+CSS 命名规范
- JMS入门_StepByStep