前言
Model:负责数据逻辑
View:负责视图逻辑
Presenter:负责业务逻辑
持有关系:
1、View 持有 Presenter
2、Model 持有 Presenter
3、Presenter 持有 View
4、Presenter 持有 Model
辅助工具:ViewBinding
执行流程:View ==> Presenter ==> Model ==> Presenter ==> View
案例效果图:
1、定义IPresenter接口
/*** 代理接口 负责业务逻辑*/
public interface IPresenter extends IBasePresenter {void setView(IView view); // 持有 Viewvoid setModel(IModel model); // 持有 Modelvoid onDataChanged(String data); // 时时修改Model的数据,由View通知 Presentervoid onDataChangedUpdateText(String data); // 修改View的TextView数据,由Model通知 Presentervoid submitFromData(); // 执行Model的 提交表单服务,由View通知 Presentervoid showSubmitFromLoading(String data); // 执行View的显示loading方法,由Model通知 Presentervoid hideSubmitFromLoading(); // 执行View的隐藏loading方法,由Model通知 Presentervoid clearData(); // 执行Model的 清空数据方法,由View通知 Presentervoid clearTextData(); // 执行View的清空TextView内容方法,由Model通知 Presenter}
1.1、实现IPresenter接口
/*** 具体业务逻辑实现*/
public class IPresenterImp implements IPresenter {private IView view;private IModel model;@Overridepublic void setView(IView view) {this.view = view;}@Overridepublic void removeHandlerMsgAndCallback() {model.removeHandlerMsgAndCallback();}@Overridepublic void setModel(IModel model) {this.model = model;}@Overridepublic void onDataChanged(String data) {model.onDataChanged(data);}@Overridepublic void onDataChangedUpdateText(String data) {view.onDataChangedUpdateText(data);}@Overridepublic void submitFromData() {model.submitFromData();}@Overridepublic void showSubmitFromLoading(String data) {view.showSubmitFromLoading(data);}@Overridepublic void hideSubmitFromLoading() {view.hideSubmitFromLoading();}@Overridepublic void clearData() {model.clearData();}@Overridepublic void clearTextData() {view.clearFromData();}}
2、定义Model接口
/*** 数据模型接口 负责数据逻辑*/
public interface IModel extends IBaseModel {default void setPresenter(IPresenter presenter) {} // 持有 Presenter/*** 这些都是方法,都是由 Presenter 调用的*/void onDataChanged(String data); // 监听文本变化,时时更新数据void submitFromData(); // 提交表单数据void clearData(); // 清空数据}
2.1、实现Model接口
/*** 数据模型逻辑 具体实现*/
public class IModelImp implements IModel {private String mData = "";private IPresenter presenter;private Handler handler = new Handler();@Overridepublic void setPresenter(IPresenter presenter) {this.presenter = presenter;}@Overridepublic void onDataChanged(String data) {mData = data;presenter.onDataChangedUpdateText(mData);}@Overridepublic void removeHandlerMsgAndCallback() {handler.removeCallbacksAndMessages(null);}@Overridepublic void submitFromData() {presenter.showSubmitFromLoading(mData);handler.removeCallbacksAndMessages(null);handler.postDelayed(new Runnable() {@Overridepublic void run() {presenter.hideSubmitFromLoading();}}, 1500);}@Overridepublic void clearData() {mData = "";presenter.clearTextData();}
}
3、定义View接口
/*** 视图接口 负责视图逻辑*/
public interface IView extends IBaseView {default void setPresenter(IPresenter presenter) {} // 持有 Presenter/*** 这些都是方法,都是由 Presenter 调用的*/void onDataChangedUpdateText(String data); // 根据时时数据更新TextViewvoid showSubmitFromLoading(String data); // 显示提交表单loadingvoid hideSubmitFromLoading(); // 隐藏提交表单loadingvoid clearFromData(); // 清空EditText数据}
3.1、实现View接口
/*** 视图逻辑 具体实现*/
public class MVPActivity extends AppCompatActivity implements IView, View.OnClickListener {private ActivityMvpBinding binding;private IModel iModel;private IPresenter iPresenter;private AlertDialog dialog;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);binding = ActivityMvpBinding.inflate(getLayoutInflater());setContentView(binding.getRoot());iPresenter = new IPresenterImp();iModel = new IModelImp();// 注意一下,写的顺序iModel.setPresenter(iPresenter); // 持有 PresentersetPresenter(iPresenter); // 持有 PresenteriPresenter.setModel(iModel); // 持有 ModeliPresenter.setView(this); // 持有 Viewinit();}@Overridepublic void onClick(View v) {if (v == binding.submitBtn) {iPresenter.submitFromData();} else if (v == binding.clearBtn) {iPresenter.clearData();}}@Overrideprotected void onDestroy() {super.onDestroy();iPresenter.removeHandlerMsgAndCallback();}private void init() {binding.editMsg.setText("normal");binding.edit.addTextChangedListener(new TextWatcher() {@Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after) {}@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {iPresenter.onDataChanged(s.toString());}@Overridepublic void afterTextChanged(Editable s) {}});binding.submitBtn.setOnClickListener(this);binding.clearBtn.setOnClickListener(this);}@Overridepublic void onDataChangedUpdateText(String data) {binding.editMsg.setText(data);}@Overridepublic void showSubmitFromLoading(String data) {AlertDialog.Builder builder = new AlertDialog.Builder(this);TextView textView = new TextView(this);if (TextUtils.isEmpty(data)) {data = "normal";}textView.setText("正在提交:" + data);builder.setCancelable(false);builder.setView(textView);dialog = builder.show();}@Overridepublic void hideSubmitFromLoading() {dialog.dismiss();}@Overridepublic void clearFromData() {binding.edit.setText("");binding.editMsg.setText("normal");}}
4、IBasePresenter
/*** Base 代理接口 负责业务逻辑*/
public interface IBasePresenter {// 写一些,公用或者通用的方法,用于扩展default void removeHandlerMsgAndCallback() {} // 删除handler 回调和消息}
5、IBaseModel
/*** Base 数据模型接口 负责数据逻辑*/
public interface IBaseModel {// 写一些,公用或者通用的方法,用于扩展default void removeHandlerMsgAndCallback() {} // 删除handler 回调和消息}
6、IBaseView
/*** Base 视图接口 负责视图逻辑*/
public interface IBaseView {// 写一些,公用或者通用的方法,用于扩展default void testBaseView() {}}
7、activity_mvp.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"tools:context=".ui.activity.MVPActivity"><androidx.appcompat.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="48dp"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"android:background="@color/material_dynamic_primary90"app:title="MVP" /><EditTextandroid:id="@+id/edit"android:layout_width="match_parent"android:layout_height="50dp"android:layout_marginHorizontal="16dp"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toBottomOf="@id/toolbar" /><TextViewandroid:id="@+id/edit_msg"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="8dp"app:layout_constraintLeft_toLeftOf="@id/edit"app:layout_constraintTop_toBottomOf="@id/edit" /><androidx.appcompat.widget.AppCompatButtonandroid:id="@+id/submit_btn"android:layout_width="match_parent"android:layout_height="58dp"android:layout_marginHorizontal="16dp"android:layout_marginTop="8dp"android:text="submit"android:textAllCaps="false"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toBottomOf="@id/edit_msg" /><androidx.appcompat.widget.AppCompatButtonandroid:id="@+id/clear_btn"android:layout_width="match_parent"android:layout_height="58dp"android:layout_marginHorizontal="16dp"android:layout_marginTop="8dp"android:text="clear"android:textAllCaps="false"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toBottomOf="@id/submit_btn" /></androidx.constraintlayout.widget.ConstraintLayout>
8、源码地址
GitHub - LanSeLianMa/AndroidMVP: Android MVP 写法