一篇文章彻底弄懂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 ...
随机推荐
- 2019牛客暑期多校训练营(第十场)F.Popping Balloons(线段树)
题意:现在给你n个点 现在让你横着划三条线间距为r 然后竖着划三条线间距同样为r 现在让你求经过最多的点数 思路:我们首先建一棵关于y区间的线段树 然后枚举x轴 每次更新重叠的点 然后再更新回去 找一 ...
- HDU6370 Werewolf 【基环内向树】
HDU6370 Werewolf 题意: 有\(N\)个人玩狼人杀,只有村民和狼人,每个人指定另一个人并指出一个身份,其中:村民是不会说谎的,狼人是有可能说谎的,问在所有情况下必然是狼人的人数和必然是 ...
- POJ - 3693 Maximum repetition substring(重复次数最多的连续重复子串)
传送门:POJ - 3693 题意:给你一个字符串,求重复次数最多的连续重复子串,如果有一样的,取字典序小的字符串. 题解: 比较容易理解的部分就是枚举长度为L,然后看长度为L的字符串最多连续出现 ...
- Codeforces Round #547 (Div. 3) F1/2. Same Sum Blocks (Easy/Hard) (贪心,模拟)
题意:有一长度为\(n\)的数组,求最多的区间和相同的不相交的区间的个数. 题解:我们可以先求一个前缀和,然后第一层循环遍历区间的右端点,第二层循环枚举左端点,用前缀和来\(O(1)\)求出区间和,\ ...
- python代理池的构建2——代理ip是否可用的处理和检查
上一篇博客地址:python代理池的构建1--代理IP类的构建,以及配置文件.日志文件.requests请求头 一.代理ip是否可用的处理(httpbin_validator.py) #-*-codi ...
- pyspark Py4JJavaError: Unsupported class file major version 56
在jupyter notebook跑上面的代码的时候报错Py4JJavaError: An error occurred while calling z:org.apache.spark.mllib. ...
- 牛客网-Beautiful Land 【01背包 + 思维】
链接:https://www.nowcoder.com/acm/contest/119/F来源:牛客网 Now HUST got a big land whose capacity is C to p ...
- codefoeces 864B
B. Polycarp and Letters time limit per test 2 seconds memory limit per test 256 megabytes input stan ...
- Oh My Zsh All In One
Oh My Zsh All In One https://ohmyz.sh/ install # CURL $ sh -c "$(curl -fsSL https://raw.github. ...
- 开放式 Web 应用程序安全性项目 OWASP
开放式 Web 应用程序安全性项目 OWASP Open Web Application Security Project (OWASP) OWASP 基金会是谁? Open Web Applicat ...