最近回顾了一下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
|