前言:

一直致力于提高开发效率降低项目耦合,今天想抽空学习一下MVP架构设计模式,学习一下如何运用到项目中。

MVP架构设计模式

MVP模式是一种架构设计模式,也是一种经典的界面模式。MVP中的M代表Model, V是View, P是Presenter。

  • Model 业务逻辑和实体模型
  • View 代表对应布局文件以及一个将UI界面提炼而抽象出来的接口。
  • Presenter Model和View之间的桥梁

为什么采用MVP

  • 降低耦合度
  • 模块职责划分明显
  • 利于测试驱动开发
  • 代码复用
  • 隐藏数据
  • 代码灵活性

举个栗子说明一下

先看下整个栗子的结构示意图

1)首先我们先看M层

Model代表业务逻辑和实体模型,栗子中的M层包含一个实体类UserEntity,具体代码如下:

public class UserEntity {
private String name;
private int age; 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;
}
}

一个获取user列表的契约接口类IUserModel

public interface IUserModel {

    void loadUserEntities(IGetUserEntitiesListener listener);
}

一个实现IUserModel的实现类UserModelImpl

public class UserModelImpl implements IUserModel {
@Override
public void loadUserEntities(final IGetUserEntitiesListener listener) {
//模拟网络请求数据过程
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
List<UserEntity> userModels = new ArrayList<>();
int testCount = 20;
for (int i = 0; i < testCount; i++) {
UserEntity userModel = new UserEntity();
userModel.setAge(i * 5);
userModel.setName(String.format("李%d", i));
userModels.add(userModel);
}
listener.onGetUserEntities(userModels);
}
}, 3000);
}
}

回调结果的IGetUserEntitiesListener 接口类

public interface IGetUserEntitiesListener {

    void onGetUserEntities(List<UserEntity> userEntities);

}

2)V层就是页面的展示与加载

这里的V层为一个接口契约类和Activity,负责View的绘制以及与用户交互,首先看下契约接口类

public interface ILoadDataView<T> {

    void startLoading();//开始加载

    void loadFailed();//加载失败

    void loadSuccess(List<T> list);//加载成功

    void finishLoading();//结束加载

}

Activity代码如下

public class MainActivity extends AppCompatActivity implements ILoadDataView<UserEntity> {
private MyAdapter mMyAdapter;
private ProgressDialog mProgressDialog;
private LoadUserEntitiesPresenter mLoadListPresenter; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
} private void initViews() {
ListView testListView = (ListView) findViewById(R.id.test_listView);
mMyAdapter = new MyAdapter(this);
testListView.setAdapter(mMyAdapter);
mLoadListPresenter = new LoadUserEntitiesPresenter(this);
findViewById(R.id.test_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mMyAdapter.removeDatas();
mMyAdapter.notifyDataSetChanged();
mLoadListPresenter.loadUserEntities();
}
});
} @Override
public void startLoading() {
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage("正在加载中");
mProgressDialog.show();
} @Override
public void loadFailed() { } @Override
public void loadSuccess(List<UserEntity> list) {
mMyAdapter.addDatas(list);
mMyAdapter.notifyDataSetChanged();
} @Override
public void finishLoading() {
if (mProgressDialog != null) {
mProgressDialog.dismiss();
mProgressDialog = null;
}
}

3)P层负责完成View于Model间的交互,由P分别操作M层和V层,是他们之间的桥梁

 首先看下Presenter的实现,包括一个ILoadUserEntitiesPresenter契约接口类和LoadUserEntitiesPresenter实现类

ILoadUserEntitiesPresenter类代码

public interface ILoadUserEntitiesPresenter {

    void loadUserEntities();

}
LoadUserEntitiesPresenter实现类
public class LoadUserEntitiesPresenter implements ILoadUserEntitiesPresenter {
private ILoadDataView<UserEntity> mILoadListView;
private IUserModel mUserModel; public LoadUserEntitiesPresenter(ILoadDataView<UserEntity> mILoadListView) {
this.mILoadListView = mILoadListView;
this.mUserModel = new UserModelImpl();
} @Override
public void loadUserEntities() {
mILoadListView.startLoading();
mUserModel.loadUserEntities(new IGetUserEntitiesListener() {
@Override
public void onGetUserEntities(List<UserEntity> userEntities) {
if (userEntities != null && !userEntities.isEmpty()) {
mILoadListView.loadSuccess(userEntities);
} else {
mILoadListView.loadFailed();
}
mILoadListView.finishLoading();
}
});
}
}

为了保证栗子能够正常运行,顺便贴出其他的代码

public class MyAdapter extends BaseAdapter {
private List<UserEntity> mUserModels;
private Context mContext; public MyAdapter(Context mContext) {
this.mContext = mContext;
this.mUserModels = new ArrayList<>();
} @Override
public int getCount() {
return mUserModels != null ? mUserModels.size() : 0;
} @Override
public Object getItem(int position) {
return mUserModels.get(position);
} @Override
public long getItemId(int position) {
return 0;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = viewHolder.bindVIew();
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.bindData(position);
return convertView;
} public void addDatas(List<UserEntity> modelList) {
if (modelList == null || modelList.isEmpty()) {
return;
}
mUserModels.addAll(modelList);
} public void removeDatas() {
mUserModels.clear();
} public class ViewHolder { private TextView mTextView; public View bindVIew() {
View convertView = LayoutInflater.from(mContext).inflate(R.layout.item_listview, null);
mTextView = (TextView) convertView.findViewById(R.id.test_textview);
return convertView;
} public void bindData(int position) {
UserEntity userModel = mUserModels.get(position);
mTextView.setText(String.format("name:%s \nage:%d", userModel.getName(), userModel.getAge()));
}
} }

MyAdapter

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.whoislcj.testmvp.MainActivity"> <Button
android:id="@+id/test_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:text="测试mvp"/> <ListView
android:id="@+id/test_listView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/> </LinearLayout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/test_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="50dp"
android:layout_margin="10dp"
android:background="@android:color/white"
android:gravity="center"
android:orientation="vertical"
android:textColor="@android:color/black"
android:textSize="16sp"/>

item_listview.xml

总结:

 这里仅仅就是MVP的简单实现,为了方便简单的认识MVP分层以及各层的职责与作用。

Android学习探索之运用MVP设计模式实现项目解耦的更多相关文章

  1. Android学习探索之Java 8 在Android 开发中的应用

    前言: Java 8推出已经将近2年多了,引入很多革命性变化,加入了函数式编程的特征,使基于行为的编程成为可能,同时减化了各种设计模式的实现方式,是Java有史以来最重要的更新.但是Android上, ...

  2. 学习RxJava+Retrofit+OkHttp+MVP的网络请求使用

    公司的大佬用的是这一套,那我这个菜鸟肯定要学习使用了. 我在网上找了很多文章,写的都很详细,比如 https://www.jianshu.com/u/5fd2523645da https://www. ...

  3. android学习日记28--Android中常用设计模式总结

    一.综述 设计模式,根据前人经验总结出常见软件工程问题的解决思想套路.GoF一共归纳了23种设计模式,当然还有人扩充,不止这些.设计模式主要利用面向对象语言的特性,而android 的设计主要用JAV ...

  4. android学习日记27--Dialog使用及其设计模式

    1.Dialog概述 对话框一般是一个出现在当前Activity之上的一个小窗口,处于下面的Activity失去焦点, 对话框接受所有的用户交互. 对话框一般用于提示信息和与当前应用程序直接相关的小功 ...

  5. Android学习探索之本地原生渲染 LaTeX数据公式

    前言: 一直致力于为公司寻找更加高效的解决方案,作为一款K12在线教育App,功能中难免会有LaTeX数学公式的显示需求,这部分公司已经实现了此功能,只是个人觉得在体验和效率上还是不太好,今天来聊一下 ...

  6. Android学习探索之App多渠道打包及动态添加修改资源属性

    前言: 关于Android渠道打包是一个比较老的话题,今天主要记录总结一下多渠道打包以及如果动态配置修改一些资源属性.今天以公司实际需求为例进行演示,由于项目复用很多公共的业务组件,而且业务组件之间的 ...

  7. Android为TV端助力 MVP设计模式!

    实现原理: MainActivity 用来更新UI,和显示业务逻辑的结果! LoginPresenterCompl 用来处理 业务逻辑 ILoginPresenter 业务处理类抽象出来的接口 ILo ...

  8. Android学习笔记(一)——新建一个项目

    //此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 1.打开Android Studio时出现以下界面,点击”start a new Android Studio ...

  9. android学习日记03--常用控件Dialog

    常用控件 9.Dialog 我们经常会需要在Android界面上弹出一些对话框,比如询问用户或者让用户选择.这些功能我们叫它Android Dialog对话框 对话框,要创建对话框之前首先要创建Bui ...

随机推荐

  1. WebSite---前台系统图片验证码心得

    背景: 因为移动端APP和Msite手机注册发送短信验证码没有添加图片验证码功能.公司的短信接口被恶意刷取.所以我们就觉得在移动端添加一个图片验证码功能.分享一下大体实现方式思路.PS demo是自己 ...

  2. JavaWeb之MVC模式

    一.什么是MVC设计模式? MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Contr ...

  3. sql查询表说明

    一条神奇的sql语句 可以查询到数据库表的说明信息.如下:希望可以帮到大家 SELECT 表名 = case when a.colorder=1 then d.name else '' end, 表说 ...

  4. <context:property-placeholder/>元素

    <context:property-placeholder/>元素 PropertyPlaceholderConfigurer实现了BeanFactoryPostProcessor接口,它 ...

  5. ATM取款~~

    package com.jredu.ch03; import java.util.Scanner; public class Atmmmmmmmmmm { static int totalMoney= ...

  6. Android Studio开发遇到程序崩溃问题

    在用Android Studio开发过程中,经常遇到程序本身没有错误,但运行起来却总是挂掉,具体有如下几个解决方案: 1.将运行在真机上的app卸载,重新运行安装 2.在Build选项中有一个clea ...

  7. Java之路——环境配置与编译运行

    本文大纲 一.开篇 二.JDK下载 三.JDK安装 四.环境配置 五.初识Java编译 六.Java与Javac 七.第一个Java程序 八.总结 九.参考资料 一.开篇 通过对之前Java之路的了解 ...

  8. unity插件开发——Selection

    Selection是一个静态类,它的主要功能是获取在project窗口中鼠标选择的对象或者是inspector窗口的当前显示的对象.它的字段有 activeGameObject activeInsta ...

  9. Ubuntu下搜狗输入法突然无法输入中文

    百度了很久的,后面看到这个帖子,找到解决办法.引用:http://blog.csdn.net/kiss_the_sky/article/details/62238529 删除配置文件,重启搜狗 ubu ...

  10. 动态代理的两种实现方式(JDK/Cglib)

    =========================================== 原文链接: 动态代理的两种实现方式(JDK/Cglib) 转载请注明出处! ================== ...