Android MVC 写法

前言

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.mfbz.cn/a/279048.html

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

相关文章

【Python排序算法系列】—— 选择排序

​ &#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 &#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 目录 选择排序 过程演示&#xff1a; 选择排序实现代码&#xff1a; 分析选择排序&#xff1a…

Word 将页面方向更改为横向或纵向

文章目录 更改整个文档的方向更改部分页面的方向方法1&#xff1a;方法2&#xff1a; 参考链接 更改整个文档的方向 选择“布局”>“方向”&#xff0c;选择“纵向”或“横向”。 更改部分页面的方向 需要达到下图结果&#xff1a; 方法1&#xff1a; 选:中你要在横向页面…

6130 树的最长路

思路&#xff1a;树的最长路问题可以通过两次 DFS 求解&#xff0c;具体思路如下&#xff1a; 1.第一次 DFS 求树的直径 以任意一个点为起点进行深度优先遍历&#xff08;DFS&#xff09;&#xff0c;找到与该点距离最远的点 u 。 以 u 为起点进行 DFS &#xff0c;找到与 u 距…

计算机网络复习5

传输层——端到端 文章目录 传输层——端到端功能传输层的寻址与端口UDPTCPTCP连接管理TCP可靠传输TCP流量控制TCP拥塞控制网络拥塞的处理 功能 从通信和信息处理的角度看&#xff0c;传输层向它上面的应用层提供通信服务&#xff0c;它属于面向通信部分的最高层&#xff0c;同…

nodejs+vue+ElementUi农产品团购销售系统zto2c

目标是为了完成小区团购平台的设计和实现&#xff0c;在疫情当下的环境&#xff0c;方便小区业主购入生活所需&#xff0c;减小居民的生活压力 采用B/S模式架构系统&#xff0c;开发简单&#xff0c;只需要连接网络即可登录本系统&#xff0c;不需要安装任何客户端。开发工具采…

jmeter之beanshell使用:常用变量汇总

1.变量--日期 使用场景&#xff1a;当入参日期是变量&#xff0c;取当前日期 使用如下&#xff1a; &#xff08;1&#xff09;当前日期 import java.text.SimpleDateFormat; import java.util.Date;// 创建 SimpleDateFormat 对象并指定日期格式 SimpleDateFormat dateFor…

Seata AT TM->RC->RM一次完整的交互过程

原理 TM两阶段&#xff1a; 阶段1&#xff1a;TM向TC申请全局事务&#xff0c;netty客户端发起了一次记录xid的请求 阶段2&#xff1a;TC协调之后&#xff0c;决定执行RM是否提交或者回滚。 spring公共组件部分 1、SeataAutoConfiguration类 利用springboot自动装配机制从…

Ubuntu 安装MySQL以及基本使用

前言 MySQL是一个开源数据库管理系统&#xff0c;通常作为流行的LAMP&#xff08;Linux&#xff0c;Apache&#xff0c;MySQL&#xff0c;PHP / Python / Perl&#xff09;堆栈的一部分安装。它使用关系数据库和SQL&#xff08;结构化查询语言&#xff09;来管理其数据。 安装…

使用Vscode远程debug报错找不到Module找不到File

1..报第一个错 提示我无法导入自己写的module 如图&#xff1a; 解决办法&#xff1a; stackoverflow上说的在launch.json中加了一条 env&#xff0c;就解决了。 "env": { "PYTHONPATH":"/home/zt/ge-sc-master/ge-sc-master"}, 2.解决完第一个…

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…

【HarmonyOS开发】案例-记账本开发

OpenHarmony最近一段时间&#xff0c;简直火的一塌糊度&#xff0c;学习OpenHarmony相关的技术栈也有一段时间了&#xff0c;做个记账本小应用&#xff0c;将所学知识点融合记录一下。 1、记账本涉及知识点 基础组件&#xff08;Button、Select、Text、Span、Divider、Image&am…

简单了解SQL宽字节注入与httpXFF头注入(基于sqllabs演示)

1、宽字节注入 sqllabs-less-32为例 使用单引号进行测试 提示我们输入的单引号被转义符 \ 进行了转义&#xff0c;即转义符自动的出现在输入的特殊字符前面&#xff0c;这是防止sql注入的一种方法&#xff0c;导致无法产生报错。 这种情况我们就可以尝试宽字节注入&#xff…

报表控件FastReport VCL 中的新 S3 传输 (Amazon)

在本文中&#xff0c;我们将探讨新的 S3 传输。从功能上来说&#xff0c;S3 与大多数人习惯使用的有很大不同&#xff0c;因此在本文的开头&#xff0c;我们将详细介绍它的主要功能。 FastReport .NET 是适用于.NET Core 3&#xff0c;ASP.NET&#xff0c;MVC和Windows窗体的全…

数据结构--二叉搜索树的实现

目录 1.二叉搜索树的概念 2.二叉搜索树的操作 二叉搜索树的插入 中序遍历(常用于排序) 二叉搜索树的查找 二叉搜索树的删除 完整二叉树代码&#xff1a; 二叉搜索树的应用 key/value搜索模型整体代码 1.二叉搜索树的概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一…

亚信安慧AntDB数据并行加载工具的实现(一)

1.概述 数据加载速度是评判数据库性能的重要指标&#xff0c;能否提高数据加载速度&#xff0c;对文件数据进行并行解析&#xff0c;直接影响数据库运维管理效率。基于此&#xff0c;AntDB分布式数据库提供了两种数据加载方式&#xff1a; 一是类似于PostgreSQL的Copy命令&am…

ES6之解构赋值详解

✨ 专栏介绍 在现代Web开发中&#xff0c;JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性&#xff0c;还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言&#xff0c;JavaScript具有广泛的应用场景&#x…

Nacos注册

一、简介 Nacos是阿里云开源的一个服务发现、配置管理和服务鉴权平台&#xff0c;它提供了一种更简单、更便捷、更开放的方式来管理服务&#xff0c;帮助开发者快速实现服务的发现、配置的管理、服务的鉴权等功能。Nacos可以帮助开发者轻松管理微服务应用中的服务提供者、服务…

《整机柜服务器通用规范》由OCTC正式发布!浪潮信息牵头编制

近日&#xff0c;中国电子工业标准化技术协会开放计算标准工作委员会&#xff08;OCTC&#xff09;正式批准发布了《整机柜服务器通用规范》&#xff0c;该标准由浪潮信息牵头&#xff0c;中国工商银行、中国质量认证中心、英特尔、中国计量科学研究院等十余家单位联合编制&…

Github 2023-12-30 开源项目日报 Top10

根据Github Trendings的统计&#xff0c;今日(2023-12-30统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量TypeScript项目4JavaScript项目2C项目1Python项目1Java项目1HTML项目1Dart项目1非开发语言项目1 令人惊叹的 …

一起玩儿物联网人工智能小车(ESP32)——13. 用ESP32的GPIO控制智能小车运动起来(一)

摘要&#xff1a;本文更深入的讲述了GPIO的相关知识&#xff0c;并完成了导线连接工作&#xff0c;为下一步的软件开发做好了准备。 通用输入输出端口&#xff08;GPIO&#xff1a;General Purpose Input/Output Port&#xff09;&#xff0c;在前面已经有了初步的介绍&#xf…