【架构】整理了一份通用的MVP框架示例代码
最近回顾了一下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>
参考:
【架构】整理了一份通用的MVP框架示例代码的更多相关文章
- Android MVP框架 详细代码
android mvp的好处,网上一搜一大堆,相对于一开始普通的在activity中处理所有的不管是网络请求还是页面渲染,最大的好处是简洁了,废话不多说,看代码 这里网络请求使用了两种,一种是自己封装 ...
- 根据网站所做的SEO优化整理的一份文档
今日给合作公司讲解本公司网站SEO优化整理的一份简单文档 架构 ########################################## 1.尽量避免Javascript和flash导航. ...
- 整理收藏一份PHP高级工程师的笔试题
整理了一份PHP高级工程师的笔试题,问题很全面.嗯,基本上这些题都答得不错,那么你应该可以胜任大部分互联网企业的PHP职位了.下面直接上题. 1. 基本知识点 HTTP协议中几个状态码的含义:503, ...
- 整理收藏一份PHP高级工程师的笔试…
注:本文转自 http://www.icultivator.com/p/5535.html 注:本文转自 http://www.yiichina.com/tutorial/57 整理了一份PHP高级工 ...
- 我自己总结的C#开发命名规范整理了一份
我自己总结的C#开发命名规范整理了一份 标签: 开发规范文档标准语言 2014-06-27 22:58 3165人阅读 评论(1) 收藏 举报 分类: C#(39) 版权声明:本文为博主原创文章, ...
- [转] 整理了一份React-Native学习指南
自己在学习React-Native过程中整理的一份学习指南,包含 教程.开源app和资源网站等,还在不断更新中.欢迎pull requests! React-Native学习指南 本指南汇集React ...
- 整理了一份React-Native学习指南
原文: http://www.w3ctech.com/topic/909 自己在学习React-Native过程中整理的一份学习指南,包含 教程.开源app和资源网站等,还在不断更新中.欢迎pull ...
- 我整理的一份来自于线上的Nginx配置(Nginx.conf),希望对学习Nginx的有帮助
我整理了一份Nginx的配置文件说明,是真正经历过正式线上考验过.如果有优化的地方,也请朋友们指点一二,整理出一份比较全而实用的配置. 主要包含配置:负载均衡配置,页面重定向,转发,HTTPS和HTT ...
- 肝了很久,冰河整理出这份4万字的SpringCloud与SpringCloudAlibaba学习笔记!!
写在前面 不少小伙伴让我整理下有关SpringCloud和SpringCloudAlibaba的知识点,经过3天的收集和整理,冰河整理出这份4万字的SpringCloud与SpringCloudAli ...
- 移动架构之MVP框架
MVP是在开发中常用的框架,要了解其原理,先要从了解MVC开始,这里就对MVP框架做一个简单的介绍 MVC MVC为Model,View与Controllor的缩写 Model:业务逻辑和实体模型 V ...
随机推荐
- 以太坊Rollup方案之 arbitrum(1)
什么是Rollup? 以太坊的Rollup扩容是一种Layer 2(第二层)扩容解决方案,旨在提高以太坊区块链的交易吞吐量和性能.它通过将大量的交易数据转移到以太坊区块链之外的第二层网络来实现这一目标 ...
- 工具 – Cypress
介绍 Cypress 是一款 e2e 测试工具.每当我们写好一个组件或者一个页面之后,我们会想对整体做一个测试. 在不使用工具的情况下,我们会开启 browser,然后做一系列点击.滚动.填 form ...
- python 属性装饰器和对应的setter方法,属性的封装和安全性控制
当我们在类中定义属性时,通常希望能够对属性的读取和写入进行控制,以确保数据的完整性和安全性.属性装饰器和对应的setter方法提供了一种实现属性封装和安全性控制的方法. 属性装饰器是Python的一种 ...
- 【赵渝强老师】Redis的消息发布与订阅
Redis 作为一个publish/subscribe server,起到了消息路由的功能.订阅者可以通过subscribe和psubscribe命令向Redis server订阅自己感兴趣的消息类型 ...
- USB gadget驱动框架(三)
gadget驱动框架(三) usb_udc与usb_gadget_driver的绑定 usb_udc与usb_gadget_driver,在注册的时候分别被添加到udc_list和gadget_dri ...
- Linux Kernel Utilization Clamping简介
随着linux内核调度技术的不断演进,目前存在多个调度类(stop.deadline.rt.cfs.idle)以满足不同性质和要求的任务(task)的调度需求.对于用户空间来说,完全公平调度器(CFS ...
- 将python文件编译成exe文件
第一种方法:我们只会生成一个exe文件,因为所有的库文件他都会包含在这个exe文件中 1.安装:pyinstaller pip install pyinstaller 2.使用如下命令编译 pyins ...
- 云原生周刊:2023 年 Java 开发人员可以学习的 25 大技术技能
文章推荐 2023 年 Java 开发人员可以学习的 25 大技术技能 这篇文章为 Java 开发人员提供了 2023 年需要学习的一些重要技能,这些技能涵盖了现代 Java 开发.大数据和人工智能. ...
- 云原生爱好者周刊:使用 Cilium 和 Grafana 实现无侵入可观测性
开源项目推荐 Cilium Grafana Observability Demo 这个项目由 Cilium 母公司 Isovalent 开源,提供了一个 Demo,使用 Cilium.OpenTele ...
- python之调用高德、百度api解析经纬度地址
调用高德 # 高德地图根据经纬度反查地址,每天只能调用5000次 def gaode_excute_single_query(coordStrings ,currentkey='你自己的api-key ...