高效开发 MVVM 和 databinding 你需要使用的工具

有不少同学已经开始使用MVVM作为自己 Android 开发架构了,但实际上,网上有关 MVVM 的资料并不是很多,这主要是因为 MVVM 还是有一定使用门槛的,并且 MVVM 不一定会帮助你提高开发效率,可能你需要写的代码更多了,或者说为了你为了让代码保持 Databinding 的双向绑定特性,而需要考虑很多业务以外的设计逻辑。我们使用一个架构或者设计模式,当然是为了更好的开发体验嘛,所以我将给大家介绍几个实用的第三方库和工具,来帮助大家解决这些问题。

MVVMLight

「MVVMLight」这个第三方库实际上是对 Databinding 工具库的一些扩展,并且通过ReplyCommandResponseCommand来对所有的 View 的事件进行统一封装,这是我认为 MVVMLight 最大的用处。

我们来看一下ReplyCommand怎么用。我们用常见的下拉刷新控件PullToRefreshLayout来举例子。

我们知道如果你想自定义一个控件的事件,你需要使用@BindingAdapter注解,比如ImageView通过URL属性直接根据地址下载图片并显示可以这样写:

这种情况往往是比较简单的,因为只是操作一个属性,但我们要自定义某一个事件该怎么办呢,比如我们要自定义onClick事件,那可能就得写接口了:

使用的时候呢,你得在 VM 中定义一个ImageOnClickListener的成员变量listener,在里面写具体的onClick实现方法,然后在 xml 中通过app:setImageOnClick="viewModel.listener"来绑定这个事件。

当然,你可以直接通过android:onClick来进行绑定,这里只是实例。

看起来好像也不是很麻烦,但是你可能每一个这样的事件,就得定义一个特殊的接口,我们能不能封装一下呢?

这就是 MVVMLight 中 ReplyCommand 和 ResponseCommand 做的事了。通过这两个类封装了各种请求参数数量和返回值参数数量的回调方法,在使用的时候,只要在泛型里具体指名请求参数和返回值的类型即可,可以说很方便了。

实例,PullToRefreshLayout 是一个刷新列表控件,我们通过使用ReplyCommand监听下拉刷新和上拉加载的监听器是这样写的:

我们使用统一的ReplyCommand来处理控件的各种事件,这里使用的是无参无返回值的最简单的情况,我们在 ViewModel 和 xml 中的写法是和之前的接口差不多的:

这样,我们所有事件的接口就统一了。ResponseCommand 和 ReplyCommand 的区别主要在,ResponseCommand 是用来定义那种有返回值的参数的,而 ReplyCommand 是没有返回值的,具体的使用方法,大家可以参考上面的链接,作者自己讲的最详细。

binding-collection-adapter

「binding-collection-adapter」对所有需要adapter的控件进行了封装,比如一些常用的:ListViewRecyclerViewViewPager等,通过使用这个库,我们就不需要再写 adapter 了,通过 databinding 的方式,在 xml 绑定一些属性,并在 ViewModel 中对这些属性进行处理即可完成这些控件的处理,逻辑清晰,代码简单。

下面举一个 RecyclerView 的例子。我们现在 xml 中定义一个 RecyclerView 控件。

我们看到有三个特殊的属性:layoutManageritemsitemBinding,这里的layoutManager大家都比较熟悉了,参数是在开头的import导入的,传入相关的类名即可。

我们先来看一下itemBinding是干什么用的,我们知道有时候列表项是可能多布局的,那么这个itemBinding就是用来处理每种布局和对应 item 的 ViewModel 的绑定关系的。上述代码的 ViewModel 中,定义了该itemBinding。

map方法中有三个参数,第一个参数是这个布局的 ViewModel,第三个参数是这个布局的 xml 文件,第二个参数这个 xml 中引入的 ViewModel 的 BR 文件 id。这样我们就绑定好了这个列表控件的多布局逻辑了。一个空数据时候的布局,一个正常返回数据时候的布局。

那么我们的数据是如何刷新的呢,这就要用到上面的items这个属性了,在我们这个例子里,它是这样定义的:

public final ObservableList<Object> viewModels = new ObservableArrayList<>();

当我们网络请求返回的时候,我们在数据回调里,通过对数据类型的处理,进行ItemViewModel的构造,最后只需要将构造好的对象一个个添加到这个ObservableList数据结构中去,界面的刷新工作都在对应的ItemViewModel里中进行处理,我们刚刚设置的itemBinding在这时候就起作用了,当新增数据的时候,它会先判断这个更新数据的ItemViewModel的数据类型,NoDataViewModel.class类型的,那么就使用R.layout.listitem_no_dataItemViewModel.class类型的,就使用R.layout.listitem_page。当然,其他的数据更新和删除操作,也会因为双向绑定而同步刷新。

我们完全从 Adapter 的繁琐中解放出来了!

Databinding support

这是一个 Android Studio 插件,我们写 xml 中的一些 Databind 代码比如<layout><data><variable><import>等标签的使用还是比较多的,而且写起来也比较繁琐,这个插件就是可以帮助你解放双手,只需要在适当的地方按⌥+⏎(Windows 是 Alt+Enter)即可,从官网盗几张 Gif 图给大家感受一下吧。

Wrap with <layout></layout>

Add <data> tag

Wrap with @{}

Wrap with @={}

Switch @{} and @={}

Add <import>

Add <variable>

MVVM 自动代码生成

MVVM 和 MVP 这种架构并不一定会让我们代码量减少,每一个界面可能都要以一种固定的模式创建很多类,那我们为什么不通过一种自动代码生成工具来通过简单的配置就完成这些类的创建呢,Java 完全就可以实现这些功能。网上有很多用 Java 实现的自动生成代码的方式,但每个人实现的 MVP 和 MVVM 架构方式都不同,所以自动化代码也会不同,我来展示下我这边使用的过程吧。

我使用的 MVVM 代码生成工具的主要思路是比较简单粗暴的,通过一个 xml 文件配置一些属性,比如起一个名字,设置一下文件输出的路径,然后在 Java 里用字符串拼接和文件流读取的方式来生成模板代码。

原文发布于微信公众号 - Android机动车(JsAndroidClub)

原文发表时间:2017-11-07

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏阮一峰的网络日志

Bookmarklet编写指南

前一段日子,我写了两个Bookmarklet----"短网址生成"和"短网址还原"。 它们用起来很方便,除了我本人之外,其他朋友也在用。第一次发布Bookmar...

49790
来自专栏小狼的世界

封装内容和功能 – YUI TabView使用小记

本文主要内容取自 Caridy Patino 在2008年发布的文章,原文中使用的是YUI2,笔者对例子做了一些更新,均使用了YUI3.1.1,文章中讨论的这个...

13120
来自专栏程序员互动联盟

【答疑释惑】Linux下面tcsh和bash的区别

在我们的公众号里面遇到有人问tcsh和bash的区别: ? 正如小编回复的那样,这个问题其实不用太去纠结,拿到一个常用的去学习就行了。不过这里还是大致说下这两个...

33150
来自专栏贺贺的前端工程师之路

React中的Redux

整个应用的state被存储在一棵object tree中,并且这个object tree只存在于唯一一个store中。

13020
来自专栏Golang语言社区

Golang 中的并发限制与超时控制

前言 上回在 用 Go 写一个轻量级的 ssh 批量操作工具 里提及过,我们做 Golang 并发的时候要对并发进行限制,对 goroutine 的执行要有超时...

98360
来自专栏Seebug漏洞平台

34c3 部分Web Writeup

34c3应该算是2017年年末的最后一个惊喜了,比赛题目虽然有非预期导致难度降了很多,但是从CTF中能学到什么才是最重要的,其中Web有3个XSS题目,思路非常...

469100
来自专栏前端布道

JavaScript之Event Loop

先看段代码: console.log(1); setTimeout(function () { console.log(2); new Pr...

318120
来自专栏前端布道

全方位理解JavaScript的Event Loop

下面我们一个一个的来了解 Event Loop 相关的知识点,最后再一步一步分析出本段代码最后的输出顺序。

11530
来自专栏不止是前端

TS+React+Router+Mobx+Koa打造全栈应用

52270
来自专栏小樱的经验随笔

IPython使用学习笔记

学习《利用python进行数据分析》第三章 IPython:一种交互式计算和开发环境的笔记,共享给大家,同时为自己作为备忘用。 ? 安装ipython用pip即...

50250

扫码关注云+社区

领取腾讯云代金券