Android MVC 写法

news2024/11/23 2:25:15

前言

Model:负责数据逻辑

View:负责视图逻辑

Controller:负责业务逻辑

持有关系:

1、View 持有 Controller

2、Controller 持有 Model

3、Model 持有 View

辅助工具:ViewBinding

执行流程:View  ==> Controller ==> Model ==> View

案例效果图:

1、定义Controller接口

/**
 * 控制器接口 负责业务逻辑
 */
public interface IController extends IBaseController {

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

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

    void onDataChanged(String data); // 监听输入文本事件,通知 Model

    void submitFrom(); // 提交表单事件,通知 Model

    void clearData(); // 清空按钮点击事件,通知 Model

}

1.1、实现Controller接口

/**
 * 业务逻辑 具体实现
 */
public class IControllerImp implements IController {

    private IModel model;

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

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

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

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

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

2、定义Model接口

/**
 * 数据模型接口 负责数据逻辑
 */
public interface IModel extends IBaseModel {

    void setView(IView view); // 持有View

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

    void onDataChanged(String data); // 监听文本变化,时时更新数据后,通知 View

    void submitFromData(); // 提交表单数据后,通知 View

    void clearData(); // 清空数据后,通知 View

}

2.1、实现Model接口

/**
 * 数据模型逻辑 具体实现
 */
public class IModelImp implements IModel {

    private String mData = "";
    private Handler handler = new Handler();
    private IView iview;

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

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

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

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

    @Override
    public void clearData() {
        mData = "";
        iview.clearFromData();
    }
}

3、定义View接口

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

    default void setController(IController controller) {} // 持有控制器,根据View事件,通知 Controller

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

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

    void showSubmitFromLoading(String data); // 显示loading

    void hideSubmitFromLoading(); // 隐藏loading

    void clearFromData(); // 清空EditText数据

}

3.1、实现View接口

/**
 * 视图逻辑 具体实现
 */
public class MVCActivity extends AppCompatActivity implements IView,View.OnClickListener {

    private IModel iModel; // 数据层 M
    private IController iController; // 控制器层 C
    private AlertDialog dialog;

    private ActivityMvcBinding binding;

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

        iModel = new IModelImp();
        iController = new IControllerImp();

        // 注意一下,写的顺序

        iModel.setView(this); // 持有View
        iController.setModel(iModel); // 持有Model
        setController(iController); // 持有控制器

        init();
    }

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

    @Override
    protected void onDestroy() {
        super.onDestroy();
        iController.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) {
                iController.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、IBaseController

/**
 * Base 控制器接口 负责业务逻辑
 */
public interface IBaseController {

    // 写一些,公用或者通用的方法,用于扩展

    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_mvc.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.MVCActivity">

    <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="MVC" />

    <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/AndroidMVC: Android MVC 写法

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32CubeMX教程8 TIM 通用定时器 - 输出比较

目录 1、准备材料 2、实验目标 3、实验流程 3.0、前提知识 3.1、CubeMX相关配置 3.1.1、时钟树配置 3.1.2、外设参数配置 3.1.3、外设中断配置 3.2、生成代码 3.2.1、外设初始化函数调用流程 3.2.2、外设中断函数调用流程 3.2.3、添加其他必要代码 4、常用函数 5…

云服务器ECS运维管理

目录 实时掌握CPU、内存使用情况 实时掌握存储的使用情况 定期对云服务器数据做好备份 定期检查云服务器的安全运行情况 要想保证云服务器长期稳定的使用&#xff0c;除了依靠阿里云&#xff08;云服务提供商&#xff09;的技术支持&#xff0c;自身必要的安全维护手段也是…

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

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

Zookeeper之手写一个分布式锁

前言 我之前写了一篇快速上手ZK的文章&#xff1a;https://blog.csdn.net/qq_38974073/article/details/135293106 本篇最要是进一步加深学习ZK&#xff0c;算是一次简单的实践&#xff0c;巩固学习成果。 设计一个分布式锁 对锁的基本要求 可重入&#xff1a;允许同一个应…

QT/C++ 远程数据采集上位机+服务器

一、项目介绍&#xff1a; 远程数据采集与传输 课题要求:编写个基于TCP的网络数据获取与传输的应用程序; 该程序具备以下功能: 1)本地端程序够通过串口与下位机(单片机)进行通信&#xff0c;实现数据采集任务 2)本地端程序能将所获取下位机数据进行保存(如csv文本格式等); 3…

JavaWeb——前端之JSVue

接上篇笔记 4. JavaScript 概念 跨平台、面向对象的脚本语言&#xff0c;使网页可交互与Java语法类似&#xff0c;但是不需要变异&#xff0c;直接由浏览器解析1995年Brendan Eich发明&#xff0c;1997年成为ECMA标准&#xff08;ECMA制定了标准化的脚本程序设计语言ECMAScr…

Mysql5.7主从数据库同步失败(日记文件错误)解决记录

记录一次Mysql主从数据库同步失败(日记文件错误)解决记录 查看同步状态&#xff1a; 具体错误&#xff1a; 检查mysql数据库日记 2021-06-10T03:45:43.522398Z 1 [ERROR] Error reading packet from server for channel : event read from binlog did not pass crc check; the…

NFC与ZigBee技术在智慧农业物联网监测系统中的应用

近年来&#xff0c;我国农业物联网技术飞速发展&#xff0c;基于物联网技术的智能农业监测系统有望得到较大规模的推广应用。但传统的物联网农业监测系统其网络结构层次单一&#xff0c;多采用基于有线或无线结构的节点-上位机数据采集模式&#xff0c;节点数据访问模式缺乏灵活…

音频、视频插座

音频、视频插座 常用电子元器件类型 DC电源插座 文章目录 音频、视频插座前言一、音频、视频插座二、DC电源插座1. 镀铜锡DC插座2. 镀镍DC插座总结前言 音频和视频插座在设计上具有特定的接口类型和标准,以确保兼容性和信号传输的质量。在选择插座时,需要根据设备的接口类…

云计算:OpenStack 配置云主机实例的存储挂载并实现外网互通

目录 一、实验 1. 环境 2.配置存储挂载 3.云主机实例连接外部网络&#xff08;SNAT&#xff09; 4.外部网络连接云主机实例&#xff08;DNAT&#xff09; 二、问题 1.云主机 ping 不通外部网络 2.nova list 查看云主机列表报错 3.nova list 与 virsh list --all有何区…

【音视频 ffmpeg 学习】 RTMP推流 mp4文件

1.RTMP(实时消息传输协议)是Adobe 公司开发的一个基于TCP的应用层协议。 2.RTMP协议中基本的数据单元称为消息&#xff08;Message&#xff09;。 3.当RTMP协议在互联网中传输数据的时候&#xff0c;消息会被拆分成更小的单元&#xff0c;称为消息块&#xff08;Chunk&#xff…

docker-compose Install TeamCity

前言 TeamCity 是一个通用的 CI/CD 软件平台,可实现灵活的工作流程、协作和开发实践。允许在您的 DevOps 流程中成功实现持续集成、持续交付和持续部署。 系统支持 docker download TeamCity TeamCity 文档参考项目离线包百度网盘获取

Spring Boot学习随笔- 集成MyBatis-Plus,第一个MP程序(环境搭建、@TableName、@TableId、@TableField示例)

学习视频&#xff1a;【编程不良人】Mybatis-Plus整合SpringBoot实战教程,提高的你开发效率,后端人员必备! 引言 MyBatis-Plus是一个基于MyBatis的增强工具&#xff0c;旨在简化开发&#xff0c;提高效率。它扩展了MyBatis的功能&#xff0c;提供了许多实用的特性&#xff0c;…

Qt/C++音视频开发62-电子放大/按下选择区域放大显示/任意选取区域放大

一、前言 电子放大这个功能思考了很久&#xff0c;也是一直拖到近期才静下心来完整这个小功能&#xff0c;这个功能的前提&#xff0c;主要得益于之前把滤镜打通了&#xff0c;玩出花样来了&#xff0c;只要传入对应的滤镜字符串&#xff0c;就可以实现各种各样的效果&#xf…

学习笔记:R语言基础

文章目录 一、R语言简介二、选择R的原因三、R基本数据对象&#xff08;一&#xff09;向量&#xff08;二&#xff09;矩阵&#xff08;三&#xff09;数组&#xff08;四&#xff09;因子&#xff08;五&#xff09;列表&#xff08;六&#xff09;数据框&#xff08;七&#…

LLM之RAG实战(十一)| 使用Mistral-7B和Langchain搭建基于PDF文件的聊天机器人

在本文中&#xff0c;使用LangChain、HuggingFaceEmbeddings和HuggingFace的Mistral-7B LLM创建一个简单的Python程序&#xff0c;可以从任何pdf文件中回答问题。 一、LangChain简介 LangChain是一个在语言模型之上开发上下文感知应用程序的框架。LangChain使用带prompt和few-…

数据结构入门到入土——ArrayList与顺序表

目录 一&#xff0c;线性表 二&#xff0c;顺序表 1.接口实现 三&#xff0c;ArrayList简介 四&#xff0c;ArrayList使用 1.ArrayList的构造 2.ArrayList常见操作 3.ArrayList的遍历 4.ArrayList的扩容机制 五&#xff0c;ArrayLisit的具体使用 杨辉三角 一&#x…

SONiC和ONL所依赖的Debian版本说明

Debian 的最新几个版本 下一代 Debian 正式发行版的代号为 trixie — 测试&#xff08;testing&#xff09;版 Debian 12 (bookworm) — 当前的稳定&#xff08;stable&#xff09;版 Debian 11 (bullseye) — 当前的旧的稳定&#xff08;oldstable&#xff09;版 Debian 10&a…

CentOS7 系统安装

系统下载 官方下载 清华源下载 安装流程 1. 选择安装系统 2. 选择安装语言 3. 设置网络链接 4. 设置静态IP ![img](https://img-blog.csdnimg.cn/img_convert/53bfedd54b838f95bd8bcb2efa232e23.png)设置时区 5. 磁盘设置&#xff0c;无特殊需求默认就好 6. 安装模式选择 7…

jwt 介绍

目录 1&#xff0c;jwt 的出现问题 2&#xff0c;jwt 介绍3&#xff0c;jwt 令牌的组成3.1&#xff0c;header3.2&#xff0c;payload3.3&#xff0c;signature 4&#xff0c;验证5&#xff0c;总结 身份验证相关内容&#xff1a; 浏览器 cookie 的原理&#xff08;详&#xff…