评论

收藏

[Android] 【架构】整理了一份通用的MVP框架示例代码

移动开发 移动开发 发布于:2021-11-23 11:36 | 阅读数:450 | 评论:0

最近回顾了一下MVP框架,结合阅读到的几篇不错的博客,自己整理了一份可用于实际工作的MVP框架示例代码,这里做个记录,也顺便和网友们分享一下。
代码示例演示的是一个输入员工号查询员工信息并显示的场景,查询后的界面如下:
DSC0000.png

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

具体的代码及结构说明:
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

关注下面的标签,发现更多相似文章