前言

在前几年兴起了MVVM架构设计模式,最具有代表的框架就是DataBinding,虽然这种设计架构非常新颖,但是在使用中仍然还有很多痛点,所以我当时觉得短时间这个设计架构可能不会太流行。

最近接手了新项目,使用的就是MVVM,才发现只一两年的功夫MVVM的发展竟然这么快,已经是Android开发者必备的技能之一了。

正文

DataBinding在刚开始阶段,最令我头疼的就是数据处理的问题,往往为了显示数据,我要在XML中绑定N多个字段,如果是一个中等以上的工程,还有更蛋疼的问题,例如:

  • 你的XML可能迫切的需要if或者switch这样的判断;
  • 意想不到的空指针

在2018年,Google推出JetPack库,其中的ViewModel+LIveData终于把MVVM推上了新的高度。

ViewModel

使用ViewModel需要依赖lifecycle库:

implementation "android.arch.lifecycle:viewmodel:x.x.x"implementation "android.arch.lifecycle:extensions:x.x.x"

ViewModel的创建方法主要有两种:

// 获取FragmentActivity共享的ViewModelViewModelProviders.of(FragmentActivity).get(ViewModel::class.java)// 获取FragmentActivity共享的ViewModelViewModelProviders.of(Fragment).get(ViewModel::class.java)

ViewModel的共享范围主要有两种:一种是FragmentActivity,一种是Fragment,可以根据自己的需要选择共享的范围。如果你想要一个Application级别的ViewModel,目前是不支持的,你可以自定义Application持有一个ViewModel,或者使用单例模式。

ViewModel解决的问题

1、扩大数据共享的应用场景。

一般的数据共享是Activity与Fragment的数据传递,传统做法是使用setArguments(Bundle),这种方法有以下弊端:

  • 可能无法预测setArguments会在Fragment的哪个周期完成,要进行异常判断;
  • setArguments中的数据可能会发现改变,如果是Activity直接设置Fragment的数据,耦合性很高;
  • 数据较多时,Fragment会有很多的变量,影响可读性和维护性。

使用ViewModel,可以避免以上的尴尬情况,需要什么数据就从ViewModel中取:

  • 新加数据传递,不用修改Activity的setArguments代码,Fragment也不用编写数据接收的方法;
  • 减少数据传递,不必考虑是否要删除暂时无用的代码;
  • 取数据时,请注意数据的有效性,做好判断即可;

除此之外,自定义View也可以得到ViewModel,这样某些功能耦合性非常强的自定义View开发更加便捷。不过需要注意的是View的context的上下文是Activity类型(不会是Fragment)的,所以只能使用Activity级别的数据共享。

2、解决DataBinding的视图显示问题。

如果视图的显示需要很多的数据,那么XML就会变得越来越臃肿,并且迫切需要添加一些简单的判断,例如:

如果A为空就显示B,如果B为空就先是C,如果是C为空...

虽然DataBinding支持三元运算符,能够满足if判断的需要,但是很显然在XML维护逻辑要比Java或者Kotlin要困难的多(无拼写错误提示等)。所以我们非常需要把部分代码从XML分离出来,ViewModel就非常适合担任这个角色。

修改前:

<?xml version="1.0" encoding="utf-8"?>    ...

修改后:

<?xml version="1.0" encoding="utf-8"?>...

LiveData

刚才我们已经讨论了ViewModel的用法,但是还有一个问题没有解决,那就是数据更新的问题,解决这个问题的最佳方式就是观察者模式,但是如果没有处理好观察者的注册和解绑很容易出现内存溢出。LiveData就可以完美的解决这个问题。

我们需要添加LiveData的依赖:

implementation "androidx.lifecycle:lifecycle-livedata:2.1.0"

下面是一个简单的示例:

// 名为openDrawer的Boolean类型的LiveDatapublic final MutableLiveData openDrawer = new MutableLiveData<>();// 更新openDrawer openDrawer.setValue(true)// 观察openDrawer 的值的变化openDrawer.observe(this, aBoolean -> {             Toast.makeText(this, "${aBoolean}", Toast.LENGTH_SHORT).show();        });

LiveData的子类是MutableLiveData,内部有value属性保存最新的值,订阅LiveData的变化,直接调用LiveData.observe():

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer)owner:注册的周期,会在owner销毁的时候,解绑观察者。observer:观察的值发生变化的回调函数

owner直接使用Activity或者Fragment即可。如果你还不了解Lifecycle的使用,可以查看一下相关的资料。

总结

最后我画了一张架构图,总结了一下最新的MVVM的使用架构:

Activity:处理UI问题,但是应当尽量避免这样做,尽量统一使用DataBinding。ViewModel:保存页面需要的数据,功能复杂的话可以拆分成多个。DataBinding:处理UI视图,持有ViewModel做数据展示。如果页面功能比较复杂,可以对ViewModel和DataBinding再次细分。

如果大家对MVVM有更棒的理解,欢迎留言共同学习。

推荐阅读:

2017-2020历年字节跳动Android面试真题解析(累计下载1082万次,持续更新中)

作者:珠穆朗玛小王子

jpanel不使用jframe保存的图片为空_使用DataBinding还在为数据处理头疼?这篇文章帮你解决问题相关推荐

  1. python图片保存和图片展示顺序_【IT专家】【 python 】 —— 数据预处理:(1) 读取与显示图片 + 图像通道顺序变换...

    本文由我司收集整编,推荐下载,如有疑问,请与我司联系 [ python ] -- 数据预处理: (1) 读取与显示图片 + 图像通道顺 序变换 2018/05/31 29 # ---- 用 OPENC ...

  2. qt 保存绘制图片时背景变黑_如何将照片的背景变成黑色?

    2007-05-03 背景是黑色的,怎么样才能让字变成白色 自定义BLOG各位置文字颜色代码.menu a{color:#000000;} -菜单部分(HOME.登录.注册.搜索.帮助).menu . ...

  3. 摄像头 保存到外网服务器_【小喵科技】人工智能插件进阶篇:使用多个摄像头...

    关注KittenBot公众号,学习活动两不误~ 这次双十二,你可能需要知道的几件事!!!(有更新)1 KOI离线人工智能模块(长视频)释出~ 2 喵家灵动徽章双十二上线! 3 Kittenblock1 ...

  4. hibernate savealiasentity 保存后id为空_好程序员Java教程分享Java面试题之Hibernate

    好程序员Java教程分享Java面试题之Hibernate 1.简书一下Hibernated的开发流程 第一步:加载Hibernate的配置文件,读取配置文件的参数, 第二步:创建SessionFac ...

  5. java 微信图片上传_微信小程序图片上传java端以及前端实现

    小程序的图片上传与传统的图片上传方式有一些不一样 如果你有幸看到这篇文章,恭喜你,你可以完美解决了. 话不多说,前后端代码一并奉上: (基于springmvc ) @Controller @Reque ...

  6. Java - JFrame 设置背景图片

    设置JFrame的背景图片由两种方式: 1.Jpanel类的paintComponent(Graphics g)重新绘制背景图片 2.利用LayeredPane为Swing控件增加了深度,允许组建在需 ...

  7. 小程序画布画海报保存成图片可以保存实现完整代码

    老规矩先来个效果图: 因为是截图所以会有些模糊,在真机上会比较清晰 下面针对效果图来看看里面都画了什么元素,代码在文章的最后,大家想直接拷代码可以略过这,这里是方便大家理解代码. 首先,咱们的海报有几 ...

  8. H5 画布解决跨域问题,画布保存为图片显示在页面上

    实现功能:uniapp  H5 使用画布,绘画完之后保存为图片全屏显示完整实现代码,跨域解决方案. 跨域图片解决方案一:(使用base64编码)网络图片放到画布里面绘画 跨域图片解决方案二:(使用本地 ...

  9. matlab视频保存为图片

    将如下代码保存到m文件,不是函数文件,是script文件, matlab 将视频保存为图片 可以根据需要自行修改 [filename,pathname,fileindex]=uigetfile('*. ...

最新文章

  1. 蓝桥杯java第八届第一题--购物单
  2. RAID原理及其使用方法
  3. 利用python来解析html
  4. asp.net操作Excel总结
  5. 【机器视觉】 dev_unmap_prog算子
  6. 使用exe4j打包Java程序
  7. leetcode--121. 买卖股票的最佳时机
  8. lisp中怎样调取图形_CAD的lisp程序已加载,怎样绘图?
  9. 一个数据库的所见即所得的好工具
  10. Atitit.常见的4gl 第四代编程语言  与 dsl
  11. 机器人走进开放源代码
  12. 编写一个程序,给出汉字“你” “我” “他”在Unicode表中的位置
  13. 剑指offer刷题顺序
  14. AntDesign Upload组件上传图片
  15. pixhawk启动脚本分析
  16. if函数三个条件怎么用c语言,if函数三个条件怎么用?
  17. pdf、markdown、docx文件预览
  18. acceleration transducer
  19. DENON AVR-X510BT 功放设置记录
  20. 三、elasticsearch 实际应用(碎片篇)

热门文章

  1. wpf 多线程处理同步数据_一文带你理解多线程的实际意义和优势
  2. uint8_t uint16_t uint32_t uint64_t 解析
  3. 使用Keras训练自动驾驶(使用Udacity自动驾驶模拟器)
  4. 【讲人话】Angular如何通过@ViewChildren获取实时渲染的动态DOM节点元素(@ViewChild只能获取静态的固定DOM节点)
  5. vue中轻松搞掂鼠标气泡框提示框tip跟随
  6. Contos7 克隆实例 以及 配置网络-服务-等相关信息
  7. 到这个年纪为什么我还要开始学习理解参与区块链?
  8. 使用html5进行视频播放
  9. MySQL 解压版创建用户密码
  10. Java中的static关键字的用法