Android中级——MVVM
MVVM
- MVVM是什么?
- MVVM实现
- 前提
- Model
- ViewModel
- View
MVVM是什么?
Model-View-ViewMode架构,可看作MVP改进版,将此前Presenter的逻辑操作交给ViewMode中的Binder去处理

- Mode:封装数据存储及相关操作逻辑,与MVC/MVP不同的是会提供一系列实体类与UI绑定,ViewModel修改这些数据后将数据变化告诉View
- View:处理界面逻辑但不参与业务逻辑,显示ViewModel提供的数据
- ViewModel:视图模型与视图状态的合称,为View提供一个可供显示的数据模型并收集、处理这些数据,内部的Binder用于双向绑定,还可包含多个Child ViewModel
MVVM实现
前提
在build.gradle中android节点添加如下代码(最低SDK版本为API7,Gradle版本为1.5.0-alpha1)
dataBinding{enabled = true
}
Model
创建数据实体类LoginInfo
- 继承BaseObservable
- getXXX()方法通过@Bindable注解表示该方法所返回的数据被修改时会更新UI
- setXXX()方法调用notifyPropertyChanged()告诉DataBinding该字段被更改
public class LoginInfo extends BaseObservable {private String mUser;private String mPassword;public LoginInfo(String user, String password) {mUser = user;mPassword = password;}@Bindablepublic String getUser() {return mUser;}public void setUser(String user) {mUser = user;notifyPropertyChanged(BR.user);}@Bindablepublic String getPassword() {return mPassword;}public void setPassword(String password) {mPassword = password;notifyPropertyChanged(BR.password);}
}
ViewModel
LoginModel封装维护LoginInfo、点击事件、文本改变事件
public class LoginModel {private static final String DEF_USER = "song";private static final String DEF_PASSWORD = "123";public LoginInfo mInfo;private OnLoginListener mListener;public LoginModel(OnLoginListener listener) {mListener = listener;mInfo = new LoginInfo("", "");}public TextWatcher getUserTextWatcher() {return new TextWatcher() {@Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after) {}@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {}@Overridepublic void afterTextChanged(Editable s) {mInfo.setUser(s.toString());}};}public TextWatcher getPasswordTextWatcher() {return new TextWatcher() {@Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after) {}@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {}@Overridepublic void afterTextChanged(Editable s) {mInfo.setPassword(s.toString());}};}public interface OnLoginListener {void onLoginSuccess();void onLoginFail();}public void onLoginClick(View view) {if (mInfo.getUser().equals(DEF_USER) && mInfo.getPassword().equals(DEF_PASSWORD)) {mListener.onLoginSuccess();} else {mListener.onLoginFail();}}
}
View
xml文件根节点变为layout,布局分为
- 数据部分:声明所使用到的数据实体类以及构造该对象时的引用名
- UI部分:常规控件,可直接使用数据实体类对象中的字段、方法
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"><data><variablename="model"type="com.demo.demo0.LoginModel" /></data><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_horizontal"android:orientation="vertical"><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:addTextChangedListener="@{model.getUserTextWatcher}"android:hint="User"android:text="@{model.mInfo.getUser}" /><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:addTextChangedListener="@{model.getPasswordTextWatcher}"android:hint="Password"android:text="@{model.mInfo.getPassword}" /><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="@{model.onLoginClick}"android:text="Login" /></LinearLayout></layout>
MainActivity开启线程3秒后修改数据会显示在UI
- 通过DataBindingUtil.setContentView设置布局,布局名字为R.layout.ab_cd,则对应类为AbCdBinding,为其设置Model
public class MainActivity extends AppCompatActivity implements LoginModel.OnLoginListener {private static final String TAG = "MainActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);LoginModel model = new LoginModel(this);binding.setModel(model);new Thread(new Runnable() {@Overridepublic void run() {SystemClock.sleep(3000);model.mInfo.setUser("New User");model.mInfo.setPassword("New Password");}}).start();}@Overridepublic void onLoginSuccess() {Log.d(TAG, "onLoginSuccess: ");}@Overridepublic void onLoginFail() {Log.d(TAG, "onLoginFail: ");}
}
相关文章:
Android中级——MVVM
MVVM MVVM是什么?MVVM实现前提ModelViewModelView MVVM是什么? Model-View-ViewMode架构,可看作MVP改进版,将此前Presenter的逻辑操作交给ViewMode中的Binder去处理 Mode:封装数据存储及相关操作逻辑,与MV…...
AIGC:引领人工智能和游戏产业融合的里程碑
目录 引言: 一、AIGC简介 二、AIGC的意义和作用 三、AIGC的未来展望 四、AIGC的影响和成果 五、结论 引言: 人工智能技术的快速发展在过去几年中引起了全球范围内的广泛关注和热议。其中,AIGC(Artificial Intelligence and G…...
ubuntu安装rust教程
参考【Rust】Linux上安装Rust开发环境 sudo apt-get install curl# 注意,不开代理很可能下不到,一直报403 export RUSTUP_DIST_SERVERhttps://mirrors.ustc.edu.cn/rust-static export RUSTUP_UPDATE_ROOThttps://mirrors.ustc.edu.cn/rust-static/rustu…...
iOS UIWebView与WKWebView 那些事
一、前言介绍 UIWebView 是 iOS 2 中推出的网页容器,UIWebView是最占内存的控件;直到 iOS 8 以后,苹果推出了 WebKit 框架,其中 WKWebView 正式被推出来接替 UIWebView 的位置;iOS 12 中,苹果正式弃用 UIWebView,要求开发者用 WKWebView 全面替换 UIWebView,apple 官方…...
wps/word 之 word中的两个表格 如何合并成为一个表格(已解决)
第一步:新建两个表格: 如何实现上面的两个表格合并呢? 分别选定每个表格,然后鼠标右键---》表格属性 在表格属性中的 表格---》选择 无文字环绕。 第二个表格按照同样的方法 设置 无文字环绕。 然后将中的文本行删去即可以了。选…...
02HTML功能元素
1.功能元素 1.1.列表标签 列表标签的作用: 给一堆数据添加列表语义, 也就是告诉搜索引擎告诉浏览器这一堆数据是一个整体 - HTML中列表标签的分类 无序列表(最多)(unordered list) 有序列表(最少)(ordered list) 定义列表(其次)(definition list) 1.1.1.无序列…...
并发编程-延时队列DelayQueue
数据结构学习网站: Data Structure Visualization 思维导图 DelayQueue (延时队列) DelayQueue 是一个支持延时获取元素的阻塞队列 , 内部采用优先队列 PriorityQueue 存储元素,同时元素必须实现 Delayed 接口&#x…...
Python之哈希表-遍历和有序性
Python之哈希表-遍历和有序性 有序性 字典元素是按照key的hash值无序存储的。 但是,有时候我们却需要一个有序的元素顺序,Python 3.6之前,使用OrderedDict类可以做到,3.6开 始dict自身支持。 d1 {b:33, c:True, d:[1], f:234…...
Oracle数据库完整卸载的完整步骤
时间:2023-03-15来源:系统城装机大师作者:佚名 1、停止所有Oracle服务 进入计算机管理,在服务中,找到oracle开头的所有服务,右击选择停止。 快捷键:ctrlshiftesc打开任务管理器 文章来源 Or…...
HP OfficeJet Pro 8020 如何更换碳粉盒
环境: HP OfficeJet Pro 8020 问题描述: HP OfficeJet Pro 8020 如何更换碳粉盒 解决方案: 更换碳粉盒 更换所有墨水不足的碳粉盒或空碳粉盒。 1.打开前挡盖,然后提起碳粉盒检修门。 打开打印机门 2.等待笔架停止后再继续操作…...
【Javascript】基础数据类型
目录 基础数据类型 1.number 字面量声明 数字对象方式声明 整数判断 指定返回小数位数 NaN-表示非数字值 浮点精度 解决误差 String 字面量声明 数字对象声明 连接运算符 获取长度 大小写转换 转换成大写 转换成小写 编辑 移除空白 获取单字符 编辑 截…...
【C语言】进阶——程序编译
目录 一:🔒程序环境 程序的翻译环境和执行环境 💡1.1翻译环境 预编译阶段: 编译阶段: 汇编阶段: 链接阶段: 💡1.2运行环境 二:🔒预处理详解 &…...
记录阿里云服务器(Centos7.9)部署Thingsboard(3.4.2)遇到的一些问题
记录编译Thingsboard遇到的一些问题 部署了一个thingsboard项目到阿里云服务器上,历时十一天,遇到了很多困难,国内关于Thingsboard的资料确实很少,所以想着写一篇博客记录一下,或许能够给以后编译遇到类似问题的人一些…...
docker更新容器映射端口
一个容器已经暴露了一个端口被外界使用,但是这个端口被公司不允许使用,需要修改为其他的端口,怎么办? 1、删除原容器,重启新容器 删除已启动容器,从镜像重启新容器。2、修改原容器配置文件 3、生成镜像&…...
Pr快捷键
Pr快捷键 以下快捷键都是在英文输入法下 一、隐藏顶部项目信息 Ctrl\ 注意:是反斜杠,回车上面的按键二、单独放大窗口 选中面板按~键三、放大/缩小时间轴素材 \四、自动选中素材 序列菜单-选择跟随播放指示器五、快速定位间隙 SHIFT鼠标拖动素材 …...
94. 递归实现排列型枚举
题目: 94. 递归实现排列型枚举 - AcWing题库 思路: 1.全排列问题(坑位问题)---->递归搜索树---->用dfs深度优先搜索。 2. u表示当前坑位,state[u]表示坑位u存储的数据。因为不同坑位的数据不可以重复&#…...
白水三佳电脑ERP部署
安装宝塔面板,有这个方便很多,可以省下3天的环境部署时间。 移动端, 先取移动版的压缩包,上传至服务器/www/wwwroot/目录下面,直接解压到当前目录后会生成/www/wwwroot/m/的目录,移动版就在这里面了。以下…...
电流监测芯片SGM8199A2应用电路设计
SGM8199是一系列具有电压输出功能的双向电流监测芯片,用于监测共模电压范围内分流电阻上的压降,而不受电源电压的影响。该器件具有-0.1V至26V的宽共模电压范围输入。低偏移使得在监测电流时允许分流器上的满量程最大压降为10mV。SGM8199系列提供三种固定…...
第十五章 I/O输入输出
15,1输入输出流 流是一组有序的数据序列,根据操作的类型,可分为输入流和输出流两种。I/O(Input/Output,(输出)流提供了一条通道程序,可以使用这条通道把源中的字节序列送到目的地。虽然 I/O 流疆盘文件存取有关,但是程序的源和目的…...
进程(0)——计算机的中的软硬件【Linux】
进程(0)——计算机的中的软硬件【Linux】 一.硬件:1.1 冯诺依曼结构:1.2 存储金字塔1.2.1输入设备和存储器:1.2.2输出设备和存储器: 二.软件:2.1 操作系统2.1.1 如何理解管理: 博主自…...
中国药科大学赵玉成、徐健/皖西学院韩邦兴ACS Catal|元胡中痕量高效镇痛活性成分左旋紫堇达明生物合成最后缺失步骤的解析(附招聘信息)
遇见/摘要延胡索Corydalis yanhusuo W. T. Wang,又称元胡,属于罂粟科紫堇属植物,是传统常用大宗中药,也是浙江道地药材“浙八味”之一。苄基异喹啉生物碱(BIAs)是延胡索的主要活性成分,如延胡索…...
抖音下载器完整指南:三步轻松保存无水印视频和直播回放
抖音下载器完整指南:三步轻松保存无水印视频和直播回放 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback supp…...
如何快速配置Wand-Enhancer:WeMod客户端终极增强工具使用指南
如何快速配置Wand-Enhancer:WeMod客户端终极增强工具使用指南 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/gh_mirrors/we/Wand-Enhancer Wand-Enhancer是一款专为WeMod…...
AD9371裸机程序里那些容易配错的坑:SPI片选、SYSREF与时钟链详解
AD9371裸机开发实战:SPI片选、时钟链与SYSREF配置避坑指南 当你在深夜的实验室里盯着示波器上杂乱的信号波形,AD9371评估板依然 stubbornly 保持沉默——这种场景对射频工程师来说再熟悉不过。作为一款高性能集成收发器,AD9371的裸机程序配置…...
MCP41010数字电位器实战指南:从SPI到SGM2211调压
目录 一、MCP41010 芯片定位:最简单的 SPI 数字电位器 核心参数(记住就够用) 二、引脚功能彻底吃透(8 脚 SOIC/SOT23) 3 个模拟端(最重要) 三、工作原理:把它当普通电位器用 四…...
UDS诊断实战:手把手教你用0x3D服务(WriteMemoryByAddress)刷写ECU标定值
UDS诊断实战:手把手教你用0x3D服务(WriteMemoryByAddress)刷写ECU标定值 在汽车电子开发领域,ECU标定参数的动态调整是开发调试过程中的高频需求。想象一下这样的场景:发动机控制单元(ECU)的燃油…...
Xiaomi MiMo-V2.5 系列模型公测,推理速度更快、成本更低,还推订阅优惠!
MiMo-V2.5 系列模型公测开启,功能亮点多Xiaomi MiMo-V2.5 系列模型正式开启公测,该系列包含 MiMo-V2.5、V2.5-Pro 、V2.5-TTS Series、V2.5-ASR。其中,MiMo-V2.5-Pro 专为长难 Agent 任务打造,MiMo-V2.5 覆盖绝大多数通用 Agent 场…...
小程序富文本渲染难题如何解决?mp-html组件实战指南
小程序富文本渲染难题如何解决?mp-html组件实战指南 【免费下载链接】mp-html 小程序富文本组件,支持渲染和编辑 html,支持在微信、QQ、百度、支付宝、头条和 uni-app 平台使用 项目地址: https://gitcode.com/gh_mirrors/mp/mp-html …...
终极AutoGPT身份认证实战指南:从JWT配置到安全验证的完整教程
终极AutoGPT身份认证实战指南:从JWT配置到安全验证的完整教程 【免费下载链接】AutoGPT AutoGPT is the vision of accessible AI for everyone, to use and to build on. Our mission is to provide the tools, so that you can focus on what matters. 项目地址…...
