最近回顾了一下MVP框架,结合阅读到的几篇不错的博客,自己整理了一份可用于实际工作的MVP框架示例代码,这里做个记录,也顺便和网友们分享一下。

代码示例演示的是一个输入员工号查询员工信息并显示的场景,查询后的界面如下:

本文以该场景举例来搭建一个可以通用的MVP架构,代码整体结构如下:

具体的代码及结构说明:

mvpbase:所有MVP业务通用的方法

BaseModel.java

 1 package com.song.mvpdemo.mvpbase.model;
2
3 import java.util.Map;
4
5 /**
6 * 该类抽象出不同业务获取数据的通用方法
7 */
8 public abstract class BaseModel<T> {
9 //数据请求参数
10 protected String[] mParams;
11
12 /**
13 * 设置数据请求参数
14 *
15 * @param args 参数数组
16 */
17 public BaseModel params(String... args) {
18 mParams = args;
19 return this;
20 }
21
22 /**
23 * 添加Callback并执行数据请求,具体的数据请求由子类实现
24 */
25 public abstract void execute(ModelCallback<T> modelCallback);
26
27 /**
28 * 执行Get网络请求,此类看需求由自己选择写与不写
29 */
30 public void requestGetApi(String url, ModelCallback<T> modelCallback) {
31 //这里写具体的网络请求
32 }
33
34 //执行Post网络请求,此类看需求由自己选择写与不写
35 public void requestPostApi(String url, Map params, ModelCallback<T> modelCallback) {
36 //这里写具体的网络请求
37 }
38 }

ModelCallback.java

 1 package com.song.mvpdemo.mvpbase.model;
2
3 /**
4 * Presenter层调用Model层后数据回调
5 */
6 public interface ModelCallback<T> {
7 void onSuccess(T result);
8
9 void onFailOrError();
10
11 void onCompleted();
12 }

DataModel.java

 1 package com.song.mvpdemo.mvpbase.model;
2
3 /**
4 * 该类用于创建具体的业务Model
5 */
6 public class DataModel {
7 public static BaseModel createModel(Class clazz) {
8 BaseModel model = null;
9 try {
10 model = (BaseModel) clazz.newInstance();
11 } catch (IllegalAccessException e) {
12 e.printStackTrace();
13 } catch (InstantiationException e) {
14 e.printStackTrace();
15 }
16 return model;
17 }
18 }

BasePresenter.java

 1 package com.song.mvpdemo.mvpbase.presenter;
2
3 import com.song.mvpdemo.mvpbase.view.IBaseView;
4
5 /**
6 * 不同业务Presenter层通用的操作
7 */
8 public class BasePresenter<V extends IBaseView> {
9 private V mView;
10
11 public void attachView(V baseView) {
12 mView = baseView;
13 }
14
15 public void dettachView() {
16 mView = null;
17 }
18
19 public boolean isViewAttached() {
20 return mView != null;
21 }
22
23 public V getView() {
24 return mView;
25 }
26 }

IBaseView.java

1 package com.song.mvpdemo.mvpbase.view;
2
3 public interface IBaseView {
4 void showLoading();
5
6 void hideLoading();
7
8 void showFailOrError(String msg);
9 }

BaseActivity.java

 1 package com.song.mvpdemo.mvpbase.view;
2
3 import android.app.ProgressDialog;
4 import android.os.Bundle;
5
6 import androidx.appcompat.app.AppCompatActivity;
7
8 import com.song.mvpdemo.mvpbase.presenter.BasePresenter;
9
10 public abstract class BaseActivity extends AppCompatActivity implements IBaseView {
11
12 private ProgressDialog mProgressDialog;
13
14 @Override
15 protected void onCreate(Bundle savedInstanceState) {
16 super.onCreate(savedInstanceState);
17 initPresenter();
18 if (getPresenter() != null) {
19 getPresenter().attachView(this);
20 }
21
22 mProgressDialog = new ProgressDialog(this);
23 mProgressDialog.setCancelable(false);
24 mProgressDialog.setMessage("Loading...");
25 }
26
27 @Override
28 public void showLoading() {
29 if (mProgressDialog != null && !mProgressDialog.isShowing()) {
30 mProgressDialog.show();
31 }
32 }
33
34 @Override
35 public void hideLoading() {
36 if (mProgressDialog != null && mProgressDialog.isShowing()) {
37 mProgressDialog.dismiss();
38 }
39 }
40
41 /**
42 * 初始化Presenter的实例,子类实现
43 */
44 protected abstract void initPresenter();
45
46 /**
47 * 获取Presenter实例,子类实现
48 */
49 protected abstract BasePresenter getPresenter();
50
51 @Override
52 protected void onDestroy() {
53 super.onDestroy();
54 if (getPresenter() != null) {
55 getPresenter().dettachView();
56 }
57 }
58 }

StaffInfo.java

 1 package com.song.mvpdemo.staffinfo.model;
2
3 public class StaffInfo {
4 private String staffId;
5 private String name;
6 private int age;
7 private float salary;
8
9 public StaffInfo(String staffId, String name, int age, float salary) {
10 this.staffId = staffId;
11 this.name = name;
12 this.age = age;
13 this.salary = salary;
14 }
15
16 public String getStaffId() {
17 return staffId;
18 }
19
20 public void setStaffId(String staffId) {
21 this.staffId = staffId;
22 }
23
24 public String getName() {
25 return name;
26 }
27
28 public void setName(String name) {
29 this.name = name;
30 }
31
32 public int getAge() {
33 return age;
34 }
35
36 public void setAge(int age) {
37 this.age = age;
38 }
39
40 public float getSalary() {
41 return salary;
42 }
43
44 public void setSalary(float salary) {
45 this.salary = salary;
46 }
47
48 @Override
49 public String toString() {
50 return "StaffInfo{" +
51 "staffId='" + staffId + '\'' +
52 ", name='" + name + '\'' +
53 ", age=" + age +
54 ", salary=" + salary +
55 '}';
56 }
57 }

StaffInfoDataModel.java

 1 package com.song.mvpdemo.staffinfo.model;
2
3 import android.os.Handler;
4
5 import com.song.mvpdemo.mvpbase.model.BaseModel;
6 import com.song.mvpdemo.mvpbase.model.ModelCallback;
7
8 public class StaffInfoDataModel extends BaseModel<StaffInfo> {
9
10 @Override
11 public void execute(ModelCallback<StaffInfo> modelCallback) {
12 new Handler().postDelayed(new Runnable() {
13 @Override
14 public void run() {
15 switch (mParams[0]) {
16 case ""://输入的staffid为空,则显示失败
17 modelCallback.onFailOrError();
18 break;
19 default:
20 StaffInfo staffInfo = new StaffInfo(mParams[0], "张三", 20, 20000);
21 modelCallback.onSuccess(staffInfo);
22 break;
23 }
24 modelCallback.onCompleted();
25 }
26 }, 5000);
27 }
28 }

StaffInfoPresenter.java

 1 package com.song.mvpdemo.staffinfo.presenter;
2
3 import com.song.mvpdemo.mvpbase.presenter.BasePresenter;
4 import com.song.mvpdemo.mvpbase.model.DataModel;
5 import com.song.mvpdemo.mvpbase.model.ModelCallback;
6 import com.song.mvpdemo.staffinfo.model.StaffInfo;
7 import com.song.mvpdemo.staffinfo.model.StaffInfoDataModel;
8 import com.song.mvpdemo.staffinfo.view.IStaffInfoView;
9
10 public class StaffInfoPresenter extends BasePresenter<IStaffInfoView> {
11
12 public void queryStaffInfo(String param) {
13 getView().showLoading();
14
15 DataModel.createModel(StaffInfoDataModel.class)
16 .params(param)
17 .execute(new ModelCallback<StaffInfo>() {
18 @Override
19 public void onSuccess(StaffInfo result) {
20 if (isViewAttached()) {
21 getView().showStaffInfo(result);
22 }
23 }
24
25 @Override
26 public void onFailOrError() {
27 if (isViewAttached()) {
28 getView().showFailOrError("fail");
29 }
30 }
31
32 @Override
33 public void onCompleted() {
34 if (isViewAttached()) {
35 getView().hideLoading();
36 }
37 }
38 });
39 }
40 }

IStaffInfoView.java

 1 package com.song.mvpdemo.staffinfo.view;
2
3 import com.song.mvpdemo.mvpbase.view.IBaseView;
4 import com.song.mvpdemo.staffinfo.model.StaffInfo;
5
6 public interface IStaffInfoView extends IBaseView {
7 /**
8 * 具体业务特有的方法,无法做为通用的方法提取出来
9 */
10 String getStaffId();
11
12 void showStaffInfo(StaffInfo staffInfo);
13
14 void clearStaffId();
15 }

StaffInfoActivity.java

 1 package com.song.mvpdemo.staffinfo.view;
2
3 import android.os.Bundle;
4 import android.view.View;
5 import android.widget.EditText;
6 import android.widget.TextView;
7
8 import com.song.mvpdemo.mvpbase.view.BaseActivity;
9 import com.song.mvpdemo.mvpbase.presenter.BasePresenter;
10 import com.song.mvpdemo.R;
11 import com.song.mvpdemo.staffinfo.presenter.StaffInfoPresenter;
12 import com.song.mvpdemo.staffinfo.model.StaffInfo;
13
14 public class StaffInfoActivity extends BaseActivity implements IStaffInfoView {
15 private TextView mStaffInfoTv;
16 private EditText mStaffIdEt;
17 private StaffInfoPresenter mStaffInfoPresenter;
18
19 @Override
20 protected void onCreate(Bundle savedInstanceState) {
21 super.onCreate(savedInstanceState);
22 setContentView(R.layout.activity_staffinfo);
23 initView();
24 }
25
26 private void initView() {
27 mStaffInfoTv = findViewById(R.id.tv_result);
28 mStaffIdEt = findViewById(R.id.staffId_et);
29 findViewById(R.id.btn_submit).setOnClickListener(new View.OnClickListener() {
30 @Override
31 public void onClick(View view) {
32 mStaffInfoPresenter.queryStaffInfo(getStaffId());
33 }
34 });
35
36 findViewById(R.id.btn_clear).setOnClickListener(new View.OnClickListener() {
37 @Override
38 public void onClick(View view) {
39 clearStaffId();
40 }
41 });
42 }
43
44
45 @Override
46 protected void initPresenter() {
47 mStaffInfoPresenter = new StaffInfoPresenter();
48 }
49
50 @Override
51 protected BasePresenter getPresenter() {
52 return mStaffInfoPresenter;
53 }
54
55 @Override
56 public void showFailOrError(String msg) {
57 mStaffInfoTv.setText(msg);
58 }
59
60 @Override
61 public String getStaffId() {
62 return mStaffIdEt.getText().toString();
63 }
64
65 @Override
66 public void showStaffInfo(StaffInfo staffInfo) {
67 mStaffInfoTv.setText(staffInfo.toString());
68 }
69
70 @Override
71 public void clearStaffId() {
72 mStaffIdEt.setText("");
73 }
74 }

activity_staffinfo.xml

 1 <?xml version="1.0" encoding="utf-8"?>
2 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 xmlns:tools="http://schemas.android.com/tools"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent"
7 tools:context=".staffinfo.view.StaffInfoActivity">
8
9 <TextView
10 android:id="@+id/tv_result"
11 android:layout_width="wrap_content"
12 android:layout_height="wrap_content"
13 android:layout_marginTop="50dp"
14 android:text=""
15 app:layout_constraintLeft_toLeftOf="parent"
16 app:layout_constraintRight_toRightOf="parent"
17 app:layout_constraintTop_toTopOf="parent" />
18
19 <EditText
20 android:id="@+id/staffId_et"
21 android:layout_width="200dp"
22 android:layout_height="wrap_content"
23 android:layout_marginTop="20dp"
24 android:hint="input staff id"
25 app:layout_constraintLeft_toLeftOf="parent"
26 app:layout_constraintRight_toRightOf="parent"
27 app:layout_constraintTop_toBottomOf="@id/tv_result" />
28
29
30 <Button
31 android:id="@+id/btn_submit"
32 android:layout_width="200dp"
33 android:layout_height="wrap_content"
34 android:layout_marginTop="50dp"
35 android:text="submit"
36 app:layout_constraintLeft_toLeftOf="parent"
37 app:layout_constraintRight_toRightOf="parent"
38 app:layout_constraintTop_toBottomOf="@id/staffId_et" />
39
40 <Button
41 android:id="@+id/btn_clear"
42 android:layout_width="200dp"
43 android:layout_height="wrap_content"
44 android:text="clear"
45 app:layout_constraintLeft_toLeftOf="parent"
46 app:layout_constraintRight_toRightOf="parent"
47 app:layout_constraintTop_toBottomOf="@id/btn_submit" />
48
49 </androidx.constraintlayout.widget.ConstraintLayout>

参考:

Android MVP升级路(一)乞丐版的自我救赎

Android MVP升级路(二)轻项目标配之时尚版

Android MVP升级路(三)随心所欲的旗舰版

浅谈 MVP in Android

 
 
 

【架构】整理了一份通用的MVP框架示例代码的更多相关文章

  1. Android MVP框架 详细代码

    android mvp的好处,网上一搜一大堆,相对于一开始普通的在activity中处理所有的不管是网络请求还是页面渲染,最大的好处是简洁了,废话不多说,看代码 这里网络请求使用了两种,一种是自己封装 ...

  2. 根据网站所做的SEO优化整理的一份文档

    今日给合作公司讲解本公司网站SEO优化整理的一份简单文档 架构 ########################################## 1.尽量避免Javascript和flash导航. ...

  3. 整理收藏一份PHP高级工程师的笔试题

    整理了一份PHP高级工程师的笔试题,问题很全面.嗯,基本上这些题都答得不错,那么你应该可以胜任大部分互联网企业的PHP职位了.下面直接上题. 1. 基本知识点 HTTP协议中几个状态码的含义:503, ...

  4. 整理收藏一份PHP高级工程师的笔试…

    注:本文转自 http://www.icultivator.com/p/5535.html 注:本文转自 http://www.yiichina.com/tutorial/57 整理了一份PHP高级工 ...

  5. 我自己总结的C#开发命名规范整理了一份

    我自己总结的C#开发命名规范整理了一份 标签: 开发规范文档标准语言 2014-06-27 22:58 3165人阅读 评论(1) 收藏 举报  分类: C#(39)  版权声明:本文为博主原创文章, ...

  6. [转] 整理了一份React-Native学习指南

    自己在学习React-Native过程中整理的一份学习指南,包含 教程.开源app和资源网站等,还在不断更新中.欢迎pull requests! React-Native学习指南 本指南汇集React ...

  7. 整理了一份React-Native学习指南

    原文:  http://www.w3ctech.com/topic/909 自己在学习React-Native过程中整理的一份学习指南,包含 教程.开源app和资源网站等,还在不断更新中.欢迎pull ...

  8. 我整理的一份来自于线上的Nginx配置(Nginx.conf),希望对学习Nginx的有帮助

    我整理了一份Nginx的配置文件说明,是真正经历过正式线上考验过.如果有优化的地方,也请朋友们指点一二,整理出一份比较全而实用的配置. 主要包含配置:负载均衡配置,页面重定向,转发,HTTPS和HTT ...

  9. 肝了很久,冰河整理出这份4万字的SpringCloud与SpringCloudAlibaba学习笔记!!

    写在前面 不少小伙伴让我整理下有关SpringCloud和SpringCloudAlibaba的知识点,经过3天的收集和整理,冰河整理出这份4万字的SpringCloud与SpringCloudAli ...

  10. 移动架构之MVP框架

    MVP是在开发中常用的框架,要了解其原理,先要从了解MVC开始,这里就对MVP框架做一个简单的介绍 MVC MVC为Model,View与Controllor的缩写 Model:业务逻辑和实体模型 V ...

随机推荐

  1. svg之viewbox缩放

    先看个示例 代码如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> & ...

  2. Azure 入门系列 (第二篇 Backup 和 Disaster Recovery)

    本系列 这个系列会介绍从 0 到 1 搭建一个 Web Application 的 Server. 间中还会带上一些真实开发常用的功能. 一共 6 篇 1. Virtual Machine (VM) ...

  3. JavaScript —— 简介-引入方式

    什么是JavaScript?    JavaScript的引入方式:      

  4. linux操作系统和文件系统,命令(上)

    Linux是一个类似于windows的操作系统 Linux操作系统的一种主要使用方式是通过终端软件:终端软件里只能使用键盘不能使用鼠标,在终端软件里通过输入命令完成各种任务 clear命令可以删除终端 ...

  5. K8S命名空间处于Terminating状态,如何强制删除

    一.现象 当删除命名空间后,发现该空间一直处于Terminating状态 [root@imanager-beta-arm-21756-5g5ap ~]# kubectl get ns NAME STA ...

  6. Java poi 读取 word 、 pdf

    从各个博客 CV 出来的,不好意思 pom <dependency> <groupId>org.apache.poi</groupId> <artifactI ...

  7. USB协议详解第4讲(USB描述符-标准配置描述符)

    1.USB描述符 USB描述符有设备描述符.标准配置描述符.接口描述符.端点描述符.字符串描述符,HID设备有HID描述符.报告描述符和物理描述符.今天主要是学习USB标准配置描述符的组成. 2.标准 ...

  8. 2. 王道OS-操作系统的特征,发展和分类

    1. 并发:宏观上是同时发生的,微观是交替发生的 :ps:并行:宏观和微观都是同时发生的 : ps:单核CPU同一时刻只能执行一个程序,各个程序只能并发的执行 : 多核CPU同一时刻可以同时执行多个程 ...

  9. vite 设置网络代理

    参考文档:vite 官网.node-http-proxy 完整示例: export default defineConfig({ server: { proxy: { // 字符串简写写法 '/foo ...

  10. 常用css列表

    常用css列表 color 设置文字的颜色,如: color:red; font-size 设置文字的大小,如:font-size:12px; font-family 设置文字的字体,如:font-f ...