一篇文章彻底弄懂Android-MVVM
转:
一篇文章彻底弄懂Android-MVVM
在学习一个技术之前,我们首先要搞清为什么要用它、用它以后会有什么好处,这样我们才能有兴趣的学习下去。
一、为什么要用MVVM?
我为什么要用这个什么MVVM,我就平常写和它有什么不同吗?
首先我们要说一下,使用MVVM后,程序会有哪些变化:
1.MVVM并不会提升程序的性能,甚至如果用不好还会降低性能。
2.MVVM会增大代码的总量。
3.阅读MVVM的代码你必须不停的跳来跳去,跳到你恶心想吐。
啥?你在搞笑吗?那我为什么还要用它?且慢,我还没说最重要的一条。
4.MVVM将让你的程序完全解耦。当然,是正确使用的前提下。
为了最后这一条,我们用前3条的牺牲完全不过分,真正写代码的时候,我们面对的往往不是性能的些许提升,也不是几十或几百K的包大小增大带来的问题,而是程序不停迭代所带来的程序稳定性要求。而这也是MVVM大显身手的地方,MVVM能够完全让你的业务功能组件化,让我们需要什么就调什么,并且组件可以在不同页面之间复用;在写业务组件的时候,我们可以完全集中精力,只管写组件要完成的功能,而无需分神它顾。
读到这,相信你应该对MVVM稍微有点兴趣了吧。
二、MVVM到底是什么?
MVVM,是Model、View、ViewModel三者的缩写,它是一种程序的设计框架,是一种设计思路。不同的人实现MVVM,所用的构成技术、实现以后的性能都是不一样的。千万不要觉得它有多深奥,他其实就是由一系列代码(或技术)构成的一个程序的底座。我们在良好底座上开发出来的程序稳定性更高,可扩展性更强。
下面我们挨个来来说Model、View、ViewModel。
1.Model:数据提供。
Model在程序中专门用于提供数据,不管是网络请求获得的数据,还是数据库获得的数据,统统写在Model里。Model层独立性相当强,它只用来提供数据,而不管数据是用来做什么的。
2.View:视图元素和视图元素初始化。
View在Android中指代的就是我们常见的布局文件和Activity中的元素初始化部分。总之,所有一切我们在Android上肉眼能看见的东西都是View。在View层里,我只对UI做初始化,比如将TextView设置字体大小,为Banner控件设置滚动速度等等,这些大多可以直接在布局文件中完成。
3.ViewModel:操作业务数据,并将数据呈现在View上。
ViewModel根据业务需要,从Model层调取相关数据,然后更新View层相关元素。
说起来有点抽象,别急,下面我们用一个简单的例子来解释它们怎样互相配合,你很快就会明白。
在例子中,我们使用Google提供的DataBinding技术来完成数据绑定,以实现View和ViewModel层的交互。
【时间】
例子非常非常简单,一个仓库管理的页面,一共三个元素,其中更新时间和仓库物品列表是从服务器动态获取的。
平常写的话,我们会在Activity内完成所有的操作,先进行网络请求,得到数据后为TextView设置文字、为RecycleView设置Adapter。但使用了MVVM后,代码将被拆分为三个部分,我们按View、ViewModel、Model的顺序直接上代码,随后在一一解释:
View层:
ViewModel层:
class StockManagementViewModel(mvvmViewModel: MVVMViewModel?) : BaseViewModel(mvvmViewModel) {
fun load() {
val newData = getModel(StockModel::class.java).getStockList()
val time = getModel(StockModel::class.java).getUpdateTime()
bindingData.data.clear()
bindingData.data.addAll(newData)
bindingData.updateTime = "更新时间:${time}"
bindingData.notifyChange()
}
override fun onResumed() {
super.onResumed()
load()
}
val bindingData: BindingData = BindingData(mutableListOf(), "")
data class BindingData(
@Bindable val data: MutableList,
@Bindable var updateTime: String
) : BaseObservable()
}
@BindingAdapter("android:stockGoodsViewLoader")
fun stockGoodsViewLoader(recyclerView: RecyclerView, data: List) {
recyclerView.apply {
layoutManager = LinearLayoutManager(recyclerView.context).apply {
orientation = LinearLayoutManager.VERTICAL
}
adapter = StockManagementAdapter(recyclerView.context, data)
}
}
Model层:
class StockModel(mvvmModel: MVVMModel?) : HttpModel(mvvmModel) {
fun getStockList(): List {
return mutableListOf().apply {
add(StockGood("1", "钳子", 3))
add(StockGood("2", "扳手", 12))
}
}
fun getUpdateTime(): String {
return Utils.DateUtil.getCurrentlyTimeByFormatter(Constant.DateFormat4)
}
}
View层在我们这个例子中只有一个布局文件,布局文件是DataBinding的标准写法,在标签中写好控件需要的ViewModel。
然后将TextView和RecyclerView与ViewModel中的元素绑定好。
android:text="@{stockViewModel.bindingData.component2()}"
android:stockGoodsViewLoader="@{stockViewModel.bindingData.component1()}"
View没看明白没关系,先来看ViewModel。
还记得ViewModel的作用吗,我来重复一遍:它从Model层获取数据,然后更新视图。
这里ViewModel实现了Activity的生命周期函数,onResumed是ViewModel开始执行的地方
调用Model获取数据:
val newData = getModel(StockModel::class.java).getStockList()
val time = getModel(StockModel::class.java).getUpdateTime()
更新视图
bindingData.data.clear()
bindingData.data.addAll(newData)
bindingData.updateTime = "更新时间:${time}"
bindingData.notifyChange()
这里注意, notifyChange方法是BaseObservable中的方法,用于通知视图刷新
因为我们已经在View层将数据绑定到了data和updateTime两个变量上,因此,我们只需要更新这两个变量,就可以完成View层视图的刷新,这也正是MVVM强大的地方。从这里就可以看出,View层和ViewModel层是高度解耦的,只通过两个变量相互关联,这样,ViewModel就有了非常高的独立性,可以轻而易举的被其他View调用,也可以从例子中的View层瞬间剔除,就像插上或拔出一个U盘那样简单。
Model层比较容易理解,由于只是一个例子,我们在这里并没有请求网络,实际开发过程中,你只需要使用你想使用的网络工具请求网络或调用数据库,获取到数据后返回给ViewModel层即可。
这里值得一题的是Activity中的代码:
class StockManagementActivity : MVVMActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentViewByDataBinding(R.layout.actibity_stock_management)
dataBinding.stockViewModel = getViewModel(StockManagementViewModel::class.java)
}
}
可以看到,Activity中几乎没有逻辑代码,仅仅有一行来实例化ViewModel。MVVM就这样,将业务逻辑完整从Activity中拆分为独立的三块,不仅解放了Activity,更使整个代码的逻辑清晰,可读性极强,并且功能块之间互不干扰,这也就实现了我们开头所说的组件化开发。
三、总结
怎么样,MVVM还不错吧?如果您曾经了解过MVC、MVP,相信本文一定很容易理解,MVVM只不过的它们的“升级版”,实现过程不同,目标却是相同的。这些设计思想并不是十分深奥的东西,本质就是让软件质量变得更好,如果不明白它们的原理,不仅不会让代码质量提高,反而会使程序变得不知所云,得不偿失。
另外说一下,本文主讲MVVM,DataBinding的用法和原理没有过多涉及,但相信看过本文以后,您应该对它也有了一定的了解了吧。我开头说过,MVVM实现的技术各不相同。DataBinding是Goodle出品,并且Android Studio中支持的相当不错,因此被我采用。在了解了MVVM的机制以后,你完全可以选择你想使用的技术,构建你自己的MVVM框架。如果各位有兴趣,我可以写一个关于DataBinding的文章。当然网络上关于DataBinding的也很多,大家也可以作为参考。
小生才疏学浅,文中必有遗漏和错误,十分欢迎阅读过的同学指正,大家一起讨论!
转:
一篇文章彻底弄懂Android-MVVM
一篇文章彻底弄懂Android-MVVM的更多相关文章
- 一篇文章彻底弄懂Base64编码原理
在互联网中的每一刻,你可能都在享受着Base64带来的便捷,但对于Base64的基础原理又了解多少?今天这篇博文带领大家了解一下Base64的底层实现. Base64的由来 目前Base64已经成为网 ...
- 讲IOC非常好的一篇文章--初步弄懂DI
http://jinnianshilongnian.iteye.com/blog/1413846 http://jinnianshilongnian.iteye.com/blog/pdf 之后又看了类 ...
- 一篇文章彻底弄懂CAS实现SSO单点登录原理
1. CAS 简介 1.1. What is CAS ? CAS ( Central Authentication Service ) 是 Yale 大学发起的一个企业级的.开源的项目,旨在为 Web ...
- 一篇文章彻底弄懂Base64编码原理(转载)
在互联网中的每一刻,你可能都在享受着Base64带来的便捷,但对于Base64的基础原理又了解多少?今天这篇博文带领大家了解一下Base64的底层实现. Base64的由来 目前Base64已经成为网 ...
- 知识扩展——(转)一篇文章彻底弄懂Base64编码原理
在互联网中的每一刻,你可能都在享受着Base64带来的便捷,但对于Base64的基础原理又了解多少?今天这篇博文带领大家了解一下Base64的底层实现. 一.Base64的由来 目前Base64已经成 ...
- gradle问题总结与理解(一篇文章带你理解android studio 与gradle 的关系)
前言:近日在网上找了个很不错的安卓二维码美化,由于下载的项目经常出问题,且不方便依赖使用,因此我想把它写个demo,并把源码发布到jcenter中,修改还是很顺利的,运行项目到手机也没问题,发布遇到了 ...
- 一篇文章让你了解Android各个版本的历程
2008年--至今 Android 1.5(Cupcake纸杯蛋糕): 智能虚拟键盘:使用widgets实现桌面个性化:在线文件夹(Live Folder)快速浏览在线数据:视频录制和分享:图片上传: ...
- 一篇文章了解相见恨晚的 Android Binder 进程间通讯机制【转】
本文转载自:https://blog.csdn.net/freekiteyu/article/details/70082302 Android-Binder进程间通讯机制 概述 最近在学习Binder ...
- 一篇文章彻底搞懂base64编码原理
开始 在互联网中的每一刻,你可能都在享受着Base64带来的便捷,但对于Base64的基础原理又了解多少?今天这篇文章带领大家了解一下Base64的底层实现. base64是什么东东呢? Base64 ...
随机推荐
- Codeforces Round #626 (Div. 2) E. Instant Noodles(二分图,最大公因数)
题意: 给你一个二分图,求左侧端点的所有可能子集中的点相连的右侧端点的权值的和的最大公因数. 题解: 若所有右侧端点均不在同一左侧子集中,则求所有权值的最大公因数即可 . 否则,将在相同左侧子集中的右 ...
- python的scrapy框架的使用 和xpath的使用 && scrapy中request和response的函数参数 && parse()函数运行机制
这篇博客主要是讲一下scrapy框架的使用,对于糗事百科爬取数据并未去专门处理 最后爬取的数据保存为json格式 一.先说一下pyharm怎么去看一些函数在源码中的代码实现 按着ctrl然后点击函数就 ...
- Java 窗口 绘制图形 #1
写在前面: editplus换成eclipse了 Sketchpad要钱,买不起 自己搞(rua) by emeralddarkness 建立了一个平面直角坐标系 两个变元x,y,参数i 实现了以下功 ...
- BeautifulSoup select方法
1 html = """ 2 <html><head><title>The Dormouse's story</title> ...
- Cron表达式在 定时执行专家 5.0 中的使用方式
在<定时执行专家 V5.0>程序内部使用了包含 6 位的 Cron表达式,第一个字段(second)没有使用.程序内部一直 second 位是 0.在 Cron表达式的界面上可以设置 5位 ...
- 图解算法——链表中倒数第k个节点
题目来源: 剑指 Offer 22. 链表中倒数第k个节点 leetCode 题目描述: 输入一个链表,输出该链表中倒数第k个节点.为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个 ...
- 涂颜色的RPG问题
长度为n的方格,刷3种颜色的颜料,相邻的方格颜料颜色不能相同,且首尾方格颜色不能相同.每个方格必须涂色.计算一共有多少种涂色方式. 解题思路:(1)f(1)=3,f(2)=6,f(3)=6 (2)如果 ...
- 虚拟环境之间批量pip安装包"迁移"
在某个虚拟环境中通过 pip freeze > requirements.txt 将该环境下所有的包写入文档, 然后切换至另一虚拟环境, pip install -r requirements. ...
- VSCode 开放式架构的产品实现思路
VSCode 开放式架构的产品实现思路 https://code.visualstudio.com/ 源码 https://github.com/microsoft/vscode https://gi ...
- GraphQL API In Action
GraphQL API In Action GraphQL API express $ yarn add express express-graphql graphql # OR $ npm i -S ...