Android MVP 写法

 前言

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);  // 持有 View

    void setModel(IModel model);  // 持有 Model


    void onDataChanged(String data); // 时时修改Model的数据,由View通知 Presenter

    void onDataChangedUpdateText(String data); // 修改View的TextView数据,由Model通知 Presenter


    void submitFromData(); // 执行Model的 提交表单服务,由View通知 Presenter


    void showSubmitFromLoading(String data); // 执行View的显示loading方法,由Model通知 Presenter

    void hideSubmitFromLoading(); // 执行View的隐藏loading方法,由Model通知 Presenter


    void clearData(); // 执行Model的 清空数据方法,由View通知 Presenter

    void clearTextData(); // 执行View的清空TextView内容方法,由Model通知 Presenter

}

1.1、实现IPresenter接口

/**
 * 具体业务逻辑实现
 */
public class IPresenterImp implements IPresenter {

    private IView view;
    private IModel model;

    @Override
    public void setView(IView view) {
        this.view = view;
    }

    @Override
    public void removeHandlerMsgAndCallback() {
        model.removeHandlerMsgAndCallback();
    }

    @Override
    public void setModel(IModel model) {
        this.model = model;
    }

    @Override
    public void onDataChanged(String data) {
        model.onDataChanged(data);
    }

    @Override
    public void onDataChangedUpdateText(String data) {
        view.onDataChangedUpdateText(data);
    }

    @Override
    public void submitFromData() {
        model.submitFromData();
    }

    @Override
    public void showSubmitFromLoading(String data) {
        view.showSubmitFromLoading(data);
    }

    @Override
    public void hideSubmitFromLoading() {
        view.hideSubmitFromLoading();
    }

    @Override
    public void clearData() {
        model.clearData();
    }

    @Override
    public 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();

    @Override
    public void setPresenter(IPresenter presenter) {
        this.presenter = presenter;
    }

    @Override
    public void onDataChanged(String data) {
        mData = data;
        presenter.onDataChangedUpdateText(mData);
    }

    @Override
    public void removeHandlerMsgAndCallback() {
        handler.removeCallbacksAndMessages(null);
    }

    @Override
    public void submitFromData() {
        presenter.showSubmitFromLoading(mData);
        handler.removeCallbacksAndMessages(null);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                presenter.hideSubmitFromLoading();
            }
        }, 1500);
    }

    @Override
    public void clearData() {
        mData = "";
        presenter.clearTextData();
    }
}

3、定义View接口

/**
 * 视图接口 负责视图逻辑
 */
public interface IView extends IBaseView {

    default void setPresenter(IPresenter presenter) {} // 持有 Presenter

    /**
     * 这些都是方法,都是由 Presenter 调用的
     */

    void onDataChangedUpdateText(String data); // 根据时时数据更新TextView

    void showSubmitFromLoading(String data); // 显示提交表单loading

    void hideSubmitFromLoading(); // 隐藏提交表单loading

    void 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;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMvpBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        iPresenter = new IPresenterImp();
        iModel = new IModelImp();

        // 注意一下,写的顺序

        iModel.setPresenter(iPresenter); // 持有 Presenter
        setPresenter(iPresenter); // 持有 Presenter

        iPresenter.setModel(iModel); // 持有 Model
        iPresenter.setView(this); // 持有 View

        init();
    }

    @Override
    public void onClick(View v) {
        if (v == binding.submitBtn) {
            iPresenter.submitFromData();
        } else if (v == binding.clearBtn) {
            iPresenter.clearData();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        iPresenter.removeHandlerMsgAndCallback();
    }

    private void init() {
        binding.editMsg.setText("normal");
        binding.edit.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                iPresenter.onDataChanged(s.toString());
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });
        binding.submitBtn.setOnClickListener(this);
        binding.clearBtn.setOnClickListener(this);
    }

    @Override
    public void onDataChangedUpdateText(String data) {
        binding.editMsg.setText(data);
    }

    @Override
    public 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();
    }

    @Override
    public void hideSubmitFromLoading() {
        dialog.dismiss();
    }

    @Override
    public 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.Toolbar
        android: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" />

    <EditText
        android: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" />

    <TextView
        android: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.AppCompatButton
        android: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.AppCompatButton
        android: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 写法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/278957.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++:模板进阶

C:模板进阶 前言一、非类型模板参数二、模板的特化2.1 概念2.2 类模板特化2.2.1 全特化2.2 偏特化 2.3 函数模板特化 四、模板分离编译4.1 什么是分离编译4.2 模板的分离编译4.3 解决方法 五、总结 前言 在C:模板初阶中&#xff0c;已经介绍过了模板的基本用法&#xff0c;接下…

三角形的外心、内心、中心、重心、垂心、中心、费马点

三角形的外心 即三角形的外接圆的中心。此时&#xff1a; A O B O C O AO BO CO AOBOCO 需要注意的有以下几点&#xff1a; 第一&#xff0c; A O D &#xff0c; B O E &#xff0c; C O F 不一定是直线&#xff0c;能否证明&#xff1f; \color{red}AOD&#xff0c;BOE…

2023总结与展望--Empirefree

今年一篇博客都没写过了&#xff0c;好像完全在忙在工作和生活上面了&#xff0c;珍惜自我&#xff0c;保持热情&#xff0c;2024对我好点 文章目录 &#x1f525;1. 年终总结1.1.学习工作计划1.2. 生活计划1.3 个人总结 &#x1f525;2. 未来展望 &#x1f525;1. 年终总结 1…

数据库一般会采取什么样的优化方法?

数据库一般会采取什么样的优化方法&#xff1f; 1、选取适合的字段属性 为了获取更好的性能&#xff0c;可以将表中的字段宽度设得尽可能小。 尽量把字段设置成not null 执行查询的时候&#xff0c;数据库不用去比较null值。 对某些省份或者性别字段&#xff0c;将他们定义为e…

Linux - 设置虚拟机和主机IP在同一网段(桥接)

1.查看主机ip地址等相关信息。 ipconfig -all 2.设置虚拟网络编辑器 打开虚拟网络编辑器 设置虚拟网络编辑器&#xff0c;设置为桥接模式。&#xff08;记得以管理员方式打开VMware&#xff09;。 3.修改虚拟机网卡文件 查看虚拟机ip,我们的目标是将其修改为与主机同一网段…

如何在MAC OS中的XCODE下添加 <bits/stdc++.h>

mac上使用的编译器是Clang&#xff0c;但是没有万能头文件bits/stdc.h\&#xff0c;本文介绍如何添加万能头文件 Xcode 版本&#xff1a;15.1 - 打开应用程序-Xcode-右键显示包内容 Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/includ…

Android—— MIPI屏调试

一、实现步骤 1、在kernel/arch/arm/boot/dts/lcd-box.dtsi文件中打开&dsi0节点&#xff0c;关闭其他显示面板接口&#xff08;&edp_panel、&lvds_panel&#xff09; --- a/kernel/arch/arm/boot/dts/lcd-box.dtsib/kernel/arch/arm/boot/dts/lcd-box.dtsi-5,14 …

Halcon区域生长的几种算法regiongrowing/regiongrowing_mean/watersheds

Halcon区域生长的几种算法 文章目录 Halcon区域生长的几种算法1. regiongrowing 算子2. regiongrowing_mean算子3. 分水岭算法 如果想要获得具有相似灰度的相连区域&#xff0c;可以使用区域生长法寻找相邻的符合条件的像素。区域生长法的基本思想是&#xff0c;在图像上选定一…

22 UVM Callbacks

回调用于改变组件或对象的行为而不修改其代码。请参阅SystemVerilog callback - VLSI Verify以更好地理解。UVM 中的phasing机制就是回调的一个简单示例。 1 UVM Callback Usage 允许即插即用机制以建立可重用的验证环境。基于钩子方法&#xff08;hook method&#xff09;调…

2023-12-29 服务器开发-centos-安装php8

摘要: 2023-12-29 服务器开发-centos-安装php8 centos-安装php8 必备条件 Minimal CentOS 8 / RHEL 8User with sudo rightsInternet Connection (1) 更新系统 更新系统 $ sudo dnf update $ sudo dnf upgrade 重启系统 $ sudo reboot (2) 启用 EPEL & Remi 软件库…

golang 图片加水印,字体文件从哪里找

鼠标左键双击此电脑图标在此电脑文本框输入电脑默认字体地址&#xff1a;C:\Windows\Fonts找到需要用到的字体文件&#xff0c;复制到指定文件夹

Python/R/GUI/BI类型常用数据可视化工具

什么是数据可视化工具&#xff1f; 数据可视化工具是指旨在可视化数据的所有形式的软件。它们处理数据输入&#xff0c;将其转换为用户可以根据自己的需求进行定制的视觉效果。 不同的工具可以包含不同的功能&#xff0c;但最基本的是&#xff0c;数据可视化工具提供输入数据集…

新品出击 | 软网关BLIoTLink免费发布

新品出击|软网关BLIoTLink免费发布 BLIoTLink是一款免费的物联网协议转换软件&#xff0c;可以部署在任何基于Linux OS的系统&#xff08;Linux、Debian、Ubuntu、FreeRTOS、RT-Thread&#xff09;中&#xff0c;使用灵活&#xff0c;可以实现数据的采集以及接入网络平台。 BL…

[Angular] 笔记 18:Angular Router

Angular Router 视频 chatgpt&#xff1a; Angular 具有内置的大量工具、功能和库&#xff0c;功能强大且经过良好设计&#xff0c;如组件化架构、依赖注入、模块化系统、路由和HTTP客户端等。这些功能可以直接用于项目中&#xff0c;无需额外的设置或第三方库。这简化了开发流…

mysql 26day 数据库双主双从 搭建mycat 数据库负载均衡 读写分离

目录 搭建一个(双主双从) &#xff08;然后搭建mycat&#xff09;四台主机配置master1 (主库1)master2 (主库2)slave 1(从库1)master1 (主库1)slave 1(从库1)如果配置出错 需要从这里从新配置 写入数据(测试)mycat安装java安装mycat编辑文件server.xml编辑文件schema.xml配置 m…

AI面板识别 - 华为OD统一考试

OD统一考试 (B卷) 分值: 100分 题解: Java / Python / C++ 题目描述 AI识别到面板上有N(1 ≤ N ≤ 100)个指示灯,灯大小一样,任意两个之间无重叠。 由于AI识别误差,每次别到的指示灯位置可能有差异,以4个坐标值描述AI识别的指示灯的大小和位置(左上角x1,y1,右下角x2…

智慧城市新型基础设施建设综合方案:文件全文52页,附下载

关键词&#xff1a;智慧城市建设方案&#xff0c;智慧城市发展的前景和趋势&#xff0c;智慧城市项目方案&#xff0c;智慧城市管理平台&#xff0c;数字化城市&#xff0c;城市数字化转型 一、智慧城市新基建建设背景 1、城市化进程加速&#xff1a;随着城市化进程的加速&am…

SAP问题 OPEN SQL 取不到值

关键&#xff1a;数据库中有数据&#xff0c;但是open sql取不到数据 背景&#xff1a; 标准程序在测试环境正常执行&#xff0c;在生产环境报错。 解决过程&#xff1a; 第一步&#xff1a;分析执行结果不一致可能的原因&#xff1a; 1.测试数据问题&#xff0c;可能性小&…

前端三件套html/css/js的基本认识以及示例程序

简介 本文简要讲解了html,css,js.主要是让大家简要了解网络知识 因为实际开发中很少直接写html&css,所以不必过多纠结,了解一下架构就好 希望深度学习可以参考MDN和w3school HTML 基础 HTML (Hyper Text Markup Language) 不是一门编程语言,而是一种用来告知浏览器如…

AAAI 2024:大模型如何掌握复杂工具?看孔子框架的教学之道

如今&#xff0c;大型语言模型&#xff08;LLM&#xff09;发展飞速&#xff0c;在文本和图像生成方面表现都很出色&#xff0c;但在我们的实际生活中&#xff0c;要理解和正确使用各种工具方面尚存在困难。人们期望这些模型在解决实际问题时能够灵活运用和理解各种工具&#x…