java mvp模式_MVP模式入门(结合Rxjava,Retrofit)
本文MVP的sample实现效果:
老规矩,在说对MVP模式的理解之前还是要再谈谈MVC模式,了解了MVC的缺点。我们才知道为什么要用MVP。
关于MVC的图解,我在网上找到了一些图。如下:
MVC模式在开发web或者管理系统中应用很多,我们的View与人交互,人点击鼠标或者输入一些东西时,View会发送相应的指令给Controller,Controller接到指令,再去调用Model的方法去更新数据(大多是对数据的增删改查),Model处理完,View刷新显示。
MVC模式的缺点:
1:在android中,如果我们要用mvc模式,那么每层代表什么呢?
你可能会说:View对应android的layout.xml,Model对应android中对数据库的操作对网络等操作放在这里进行,Controller对应的则是Activity!
你说的都对,但是你不觉得这样的对应关系并不好吗,如果layout.xml对应View,那如果我们想动态的控制添加一些视图控件或者改变背景,那么该怎么办呢?
答曰:在Activity中添加代码。!!!这就是缺点之一所在:Activity既当爹(View)又当妈(Controller),layout.xml代表的View层控制能力太弱。
2:再看一遍我们的MVC的结构图,View和Model是互相联系的,存在耦合关系,这就给测试维护带来了难度。当我们想更换项目中的某个零件时,缺发现 太难拆下来!这个零件类的方法散布多处。关于MVC的结构图,忘了在哪听过一句经典的话,写三个字母,M,V,C,随便用线或箭头连字母,最后就是MVC的结构图。
说完了MVC,该主角登场了,上我们MVP的结构图。
好处不言而喻,View和Model无法通信了。
View层只负责与View有关的,操作View层时发出的事件传递给Presenter,Presenter去操作Model,操作完Model,再去通知View相应更新。
关于MVP的更多概念:
接下来,看看我们在项目中如何使用MVP模式,这里顺便使用了Retrofit和RXjava,建议你先了解它们的用法。
首先看我们的需求:输入Github登录名,点击搜索按钮,搜索并显示结果(登录名,昵称, followers,following)。
最终的项目结构:
bean类:
public class User {
private String login;
private String name;
private int followers;
private int following;
public int getFollowers() {
return followers;
}
public void setFollowers(int followers) {
this.followers = followers;
}
public int getFollowing() {
return following;
}
public void setFollowing(int following) {
this.following = following;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
retrofit类主要是封装了利用Retrofit的网络请求
public interface GithubService {
@GET("/users/{user}")
Observable getUser(@Path("user") String username);
}
public class HttpMethods {
public static final String BASE_URL = "https://api.github.com";
private static final int DEFAULT_TIMEOUT = 5;
private Retrofit retrofit;
private GithubService mGithubService;
//构造方法私有
private HttpMethods() {
//手动创建一个OkHttpClient并设置超时时间
OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
httpClientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
retrofit = new Retrofit.Builder()
.client(httpClientBuilder.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl(BASE_URL)
.build();
mGithubService = retrofit.create(GithubService.class);
}
private static class SingletonHolder{
private static final HttpMethods INSTANCE = new HttpMethods();
}
//获取单例
public static HttpMethods getInstance(){
return SingletonHolder.INSTANCE;
}
public void getUser(Subscriber subscriber ,String loginName){
mGithubService.getUser(loginName)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
}
}
接下来思考我们的MVP模式了,一些从我们的View层开始,我们需要先列出和View相关的方法(不涉及逻辑)。
1.显示xml的试图
2.ProgressDialog显示
3.ProgressDialog消失
4.显示错误信息
接下来看具体代码:
activity_main.xml
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
>
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="80dp"/>
android:id="@+id/ed_text"
android:layout_centerInParent="true"
android:hint="请输入搜索登录名"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
android:id="@+id/search_btn"
android:text="查询"
android:layout_centerHorizontal="true"
android:layout_below="@+id/ed_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
BaseView,BasePresentor , BaseModel三个接口
public interface BaseView {
void showProgressDialog();
void hideProgressDialog();
void showText(User userbean);
void showErrorMessage(String text);
}
public interface BasePresenter {
void attachView(T view);
void detachView();
void searchUser(String loginName);
}
public interface BaseModel {
void getUser(Subscriber subscribe,String loginName);
}
第二个接口interface BasePresenter正是关键,至于为什么,可以用实现类去解释。
MainActivity实现BaseView接口,作为View层。
public class MainActivity extends AppCompatActivity implements BaseView {
@InjectView(R.id.tv)
TextView mTextView;
@InjectView(R.id.search_btn)
Button mButton;
@InjectView(R.id.ed_text)
EditText mEditText;
private ProgressDialog dialog;
private MainPresenter mMainPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
initView();
mMainPresenter=new MainPresenter();
mMainPresenter.attachView(this);
}
/**
* 一些初始化,这里为ProgressDialog的初始化
*/
private void initView() {
dialog=new ProgressDialog(this);
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.setMessage("正在搜索中");
}
@OnClick(R.id.search_btn)
void search(View view){
mMainPresenter.searchUser(mEditText.getText().toString());
}
@Override
public void showProgressDialog() {
dialog.show();
}
@Override
public void hideProgressDialog() {
dialog.dismiss();
}
@Override
public void showText(User userbean) {
String temp=getResources().getString(R.string.user_format);
String str=String.format(temp,userbean.getLogin(),userbean.getName(),userbean.getFollowers(),userbean.getFollowing());
mTextView.setText(str);
}
@Override
public void showErrorMessage(String text) {
Toast.makeText(this,text,Toast.LENGTH_SHORT).show();
}
@Override
protected void onDestroy() {
super.onDestroy();
if(mMainPresenter!=null)
mMainPresenter.detachView();
}
}
当点击Button产生事件时,是将逻辑交给MainPresenter去处理的,对应关系 V ——> P
下面看MainPresenter代码和Model代码。
public class MainPresenter implements BasePresenter {
private BaseView mMainView;
private MainModel mModel;
public MainPresenter() {
mModel=new MainModel();
}
@Override
public void attachView(BaseView view) {
mMainView=view;
}
@Override
public void detachView() {
mMainView=null;
}
@Override
public void searchUser(String loginName) {
if(TextUtils.isEmpty(loginName.trim())){
mMainView.showErrorMessage("请输入合法登录名");
return;
}
if (mModel!=null){
mModel.getUser(new Subscriber() {
@Override
public void onStart() { //先显示对话框
mMainView.showProgressDialog();
}
@Override
public void onCompleted() { //请求结束,对话框消失
mMainView.hideProgressDialog();
}
@Override
public void onError(Throwable e) { //error时
mMainView.showErrorMessage("搜索失败");
}
@Override
public void onNext(User user) {
mMainView.showText(user);
}
},loginName);
}
}
}
public class MainModel implements BaseModel{
@Override
public void getUser(Subscriber subscriber ,String loginName) {
HttpMethods.getInstance().getUser(subscriber,loginName);
}
}
这里的Model实现类较为简单,直接使用了封装好的HttpMethods的方法。(Model可以理解为一个仓库管理员,我们的网络也能理解为一个大的仓库)。
在MainPresenter中我们其实是使用了Model的方法,即P——>M
然后用Rxjava的观察者观察结果,再去调用View的方法刷新界面,即P——>V
这时候回过来头来看我们的MVP图,是不是一模一样?(如何想要进阶mvp,可以试试契约类)
java mvp模式_MVP模式入门(结合Rxjava,Retrofit)相关推荐
- java mvp设计模式_MVP设计模式
MVP设计模式 在Android项目中,Activity和Fragment占据了大部分的开发工作.如果有一种设计模式(或者说代码结构)专门是为优化Activity和Fragment的代码而产生的,你说 ...
- java mvp模式_mvp开发模式是什么意思(半分钟了解mvp模式)
MVC 模式 Model-View-Controller ,模型-视图-控制器模式 Model:针对业务模型,建立的数据结构,Model 与 View 无关,而与业务有关. View:Android ...
- Android开发模式之RxJava+Retrofit+MVP(kotlin)
一共分为两部分,第一部分是RxJava+Retrofit网络请求的使用,一部分是MVP模式结合网络请求 一,RxJava+Retrofit的使用 ①module引入 里面已经封装了OkHttp和Gso ...
- TLint for 虎扑体育 基于Dagger2+RxJava+Retrofit开发,采用MVP模式
TLint 类别: 完整源码 打分: ★★★★★ 更新: 2016-05-12 09:54 大小: 6976 kb 开发环境: Android Studio 浏览: 484 次 下载: 83 次 项目 ...
- Android RxJava+Retrofit+MVP 入门总结
前言 RxJava+Retrofit+MVP的使用已经推出一段时间了,也一直想找个时间学习一下并且应用到接下来的项目中.趁放假这段时间仔细研究了一下,确实相比于其他框架的学习成本要高一些,不过功能实现 ...
- MVC、MVP、MVVM模式的概念与区别
------<MVC.MVP.MVVM模式的概念与区别> 前言: 预热: 挨个讲讲: MVC MVP MVVM 结尾: 前言: 首先MVC,MVP,MVVM都是为了解决UI页面与逻辑代码分 ...
- 设计模式——行为型模式之责任链模式(简简单单入门责任链,理解I/O流消息怎么逐步传递处理以及服务器框架转发)
文章目录 前言 一.责任链模式定义 二.责任链模式结构 三.责任链高级应用 四.责任链模式优缺点 设计模式系列文章 结尾 前言 作者更有一系列设计模式文章(还在持续更新),图例丰富,少量代码,适合入门 ...
- MVC、MVP、MVVM 模式(待续)
本文将从收集来的资料整理分析MVC模型的各种应用以及其演化历程 一. 介绍 MV* 模式 MVC.MVP.MVVM 模式都是为了解决图形界面应用程序复杂性管理问题而产生的应用架构模式.追根溯源,从最经 ...
- java备忘录模式应用场景_图解Java设计模式之备忘录模式
图解Java设计模式之备忘录模式 游戏角色状态恢复问题 游戏角色有攻击力和防御力,在大战Boss前保存自身的状态(攻击力和防御力),当大战Boss后攻击力和防御力下降,从备忘录对象恢复到大战前的状态. ...
最新文章
- 20071025-吉武
- 快速简单高效的搭建 SolrCloud 集群
- CCF201403-1 相反数
- 2018年手机摄像头模组市场调研报告
- java json删除指定元素_简洁而优雅,Python Tablib实现将数据导出为Excel, Json等N种格式...
- [渝粤教育] 西南科技大学 信息法律法规 在线考试复习资料2021版
- Java线程池关闭1-shutdown和isTerminated
- html5的ajax上传图片,html5标准Ajax上传图片
- linux访问mdio接口函数,Linux 下smi/mdio总线通信
- 互联网日报 | 58同城签署私有化协议;支付宝将发放百亿全国通用消费券;碧桂园开天猫店上线特价商品房...
- AT070TN83调试总结(时序)
- 贯头山酒——中华酒文化的源头之一
- 香港传媒高层访团莅临深之蓝参观访问
- 标准差和标准误差的区别
- tplink 智能dhcp服务器,tplink路由器设置:桥接提示“获取IP地址失败,请检查主路由器DHCP服务器是否开启”...
- RPC框架简析--Pigeon
- 手机HTML拼图验证,jQuery支持移动端的滑动块拼图验证插件
- 中国全民人寿保险市场趋势报告、技术动态创新及市场预测
- 如何建立有效的激励机制
- Bootstrap响应式Web开发(一)
热门文章
- SwipeRefreshLayout + RecyclerView 实现 上拉刷新 和 下拉刷新
- JAVA自定义Mybatis注解
- Linux 环境边配置边学(针对家里电脑) 【五】
- WinAPI: SetRectEmpty、IsRectEmpty
- mysql从库数据源_SoapUI Pro教程:如何使用MySQL服务器作为数据源-从MySQL数据库获取数据...
- python可以用来写什么_对于一个OIer,Python能干些什么?
- 五年级计算机课程内容,五年级信息技术教学计划
- python数据框拼接_pandas数据拼接的实现示例
- 本地计算机策略未创建,未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序...
- 基于八叉树的区域增长点云分割算法