Android下MVVM-Databinding框架
引言
MVVM和Databinding是当前非常流行且实用的框架和工具,相信大家已经对MVC、MVP、MVVM框架以及Databinding有一定的了解。本篇文章主要介绍一个基于Databinding封装的MVVM框架,并且结合当下非常火的Android Architecture Components库可以实现一种更简单的MVVM框架。
一、MVVM-Databinding框架背景
开篇先来了解下MVVM和Databinding及其各自优势,才能说明我们为什么要不辞辛劳的合二为一,并希望最终达到1+1>2的效果。
1. MVVM框架简介及优势
2. 数据绑定框架DataBinding简介及优势
3. MVVM-DataBinding框架简介
二、MVVM-Databinding框架详解
下面我将通过三部分介绍我的MVVM-Databinding框架:1.如何使用本框架2.本框架的实现过程。3.本框架的优点及可能的隐患。
1、如何使用本框架
通常我们开发过程中会在Activity、Fragment、楼层、列表item中使用UI控件,所以我们的框架也将支持这几种情况的数据绑定。俗话说“无规矩不成方圆”,我们通过定义少量规则来避免使用Databinding中的大量规则,进而提高代码可读性。以下是我们约定的五点规则:
① 我们约定把Activity、Fragment绑定的数据放在xxxViewModel中,楼层绑定的数据放在楼层类(代码中的xxxFloor)中,列表item绑定的数据放在ViewHolder中。就是说要绑定的数据都会放在其处理逻辑的类中。
② Activity和Fragment的布局文件要做些改变,要绑定的数据类名称(如xxxViewModel)使用"viewModel",其类型为要绑定数据的全路径类名。如下图示例:
③ 楼层的布局文件中引用的数据类使用名称为"floor",类型也是要绑定数据的全路径类名,如下图示例:
④ 列表的item布局文件中引用的数据类使用名称为"item",其类型也是要绑定数据的全路径类名。如下图示例:
⑤ 数据的控制逻辑尽量写在处理逻辑的类中,不要写在布局文件中,写在布局文件中会给排查问题造成困难并且造成他人阅读代码困难。
以上是本框架制定的简单规则,剩下的工作基本上跟接入MVP框架相似,与MVP不同的就是我们会修改相应的布局文件达到UI和数据绑定的目的。以下是接入框架的步骤:
1)创建ViewModel/楼层/ViewHolder继承自BaseViewModel/BaseFloorView/BindingViewHolder,里面可以创建要绑定的数据,例如下图:
2)创建layout文件,按照之前的规则配置要绑定的数据。如指定生成的绑定类名为“DemoNormalFragmentBinding”,名称为"viewModel",其类型为第一步的ViewModel的全路径,绑定布局和控件例如“android:text="@{viewModel.pageTitle}"”,如图:
3)创建Activity、Fragment并继承BaseBindingMvvmActivity或BaseBindingMvvmFragment,继承时需要指定绑定的ViewModel类和Binding类,这一步就完成了数据和布局UI的绑定。楼层和列表item需要完成的是ViewHolder中数据和布局UI的绑定。例如:
完成了上面这三步,就已经完成了布局和数据的绑定,你需要做的就只是写数据变化的逻辑了,只要数据改变对应的UI就会改变了。
是不是很神奇?比MVP更简洁吧?
2、本框架的实现过程
先来看下框架的代码结构,如图:
代码一共分四部分,第一部分为公共的ViewBindingAdapter,主要功能是实现公共自定义控件的绑定注入。第二部分为Activity、Fragment、Viewmodel相关基类。第三部分为楼层相关基类。第四部分为Recyclerview列表相关基类。
这里以楼层框架为例,进行相关实现机制的讲解:
1)创建布局文件,生成BR文件占位资源。BR文件是Databinding编译期间生成的,跟R文件类似,主要作用是当数据改变后,可以用该标识符通知 DataBinding,用新的数据去更新UI。这里占位的目的是在SDK中生成一个通用的名称,在其他引用SDK的项目中引用。
2)实现绑定Binding类并设置数据,就是这个步骤省去了开发者手动设置绑定的工作。其实就是调用了Databinding的通用绑定方法,这样就不用开发者显示的调用这个方法了。
3)由于楼层就是一个Recyclerview的列表组成的,可以继承基类Adapter ,在onBindViewHolder调用show方法,并且调用excutePendingBindings()方法触发刷新。
以上是我楼层实现MVVM-Databinding框架的过程,如果不关心实现过程的开发者可以直接看下demo就可以上手了。下图是楼层demo的实现效果:
3、本框架的优点及可能的隐患
这个框架大部分优点其实是结合了MVVM和Databinding的优点,如:
1.减少findViewbyId造成的IO操作性能损耗,这是Databinding的一条优点,因为Databinding在编译期间就将控件从布局映射到在Binding类中,只是在绑定阶段一次性实例化这些控件就直接可以使用,省去了findViewbyId的IO操作。
2.减少频繁线程切换,这条也是由Databinding的优点,你可以在任何你想要的线程上进行更新,因为Databinding是在UI线程进行响应。
3.减少逻辑代码冗余、提高编码效率,这条优点就是本框架的优势所在,也是为什么要将这两种优秀框架集合在一块的原因。
4.削减DataBinding的混乱规则,这是单纯的使用DataBinding体验较差的地方,在我们的框架里可以摒弃其复杂的规则。
5.更简单的单元测试,这是MVVM框架的优点,由于其天然的低耦合性,可以使我们单元测试更简单。
可能的隐患:
1.由于DataBinding在xml提供了丰富的操作符,但是由于Android studio天生的xml语法检查的贫弱,xml布局中的表达式逻辑错误,不能准确定位,导致debug难度增加,事实上一些BindingAdapter的错误在build的时候也会被提示xml错误。我在开发过程中遇到过几次,常常需要重启Android studio才能消除问题,这个问题只能寄希望于谷歌在其IDE上解决。
2.由于DataBinding是在预编译时期生成一些布局和代码,这可能导致许多需要动态加载资源或代码的工程(比如插件化工程)需要做些改变。当然普通的APP开发使用这个框架是没问题的。
当然如果你按照以上步骤改造了自己的APP,可能过程中还会遇到一个问题,就是ViewModel中上下文引用的问题,当然如果能用应用级别的context当然最好,但是有时候我们必须用activity的context时可能就有些困难了,因为我们不推荐ViewModel持有context,这样做可能造成内存泄漏,这时候我们可以结合Android Architecture Components来实现context的获取,在我的github的工程中有两个分支,其中mvvm-databinding-aac分支就是结合了Android Architecture Components来实现的。
三、结语
数据绑定的应用软件开发是一种趋势,使用DataBinding的优点显而易见。在我们选择框架的过程中需要考虑诸多问题,比如性能问题、使用便捷程度、单元测试、是否相互独立等。当然还有一点很重要的就是,共同开发的同事是否认同并喜欢这种开发方式,毕竟这会影响到他们的开发流程,习惯和体验。如何说服他们认可这种框架,就需要你提供便捷和健壮的封装框架,使他们很爽很开心很便捷地使用这种框架,并且能够满足项目代码的可扩展性,解耦和相关独立。做到这些,就能满足调用者,项目代码健壮性,模块独立性和可扩展性的需要了。我以上讲述算是抛转引玉吧,希望能共同完善框架,共同进步。