Android-DataBinding-原理-编译期
概述
- DataBinding框架分为两部分:编译期和运行时;编译期根据XML中声明式的绑定表达式以及一系列注解自动生成代码ViewDataBinding类;运行时通过特定方法(notifyPropertyChanged)对某些绑定表达式标记脏数据,下一帧根据dirtyFlag对View进行更新;
- 编译期原理主要根据编译产物或者中间产物,进行反推;运行期原理根据源码分析;
- 编译期比较复杂,所以只是结合网上相关资料和编译产物进行反推,大概了解编译期做了哪些工作;
网上相关资料
- 之前在网上看到过一篇讲述编译期的简单介绍(https://www.jianshu.com/p/eb29c691d370
),这里做个大概描述,后面会根据DataBinding最新版本的编译产物进行一些验证;
-
ANDROID_DataBinding_Compiler.png
- 白色部分为输入;黄色部分为编译器处理类;蓝色部分为中间产物;绿色部分为最终产物;
- 白色
- 黄色
- aapt编译时处理:MakeCopy.java;
- gradle-api处理:DataBinderPlugin.java;
- AbstractProcessor处理:ProcessDataBinding.java;
- 蓝色
- data-binding-info文件夹:包含layout中的变量,绑定表达式相关信息;
- setter_store.bin:包含所有setter相关信息;
- layoutinfo.bin:包含所有layout相关信息;br.bin:包含所有BR相关信息;
- 绿色
- data-binding-layout-out:保存layout中view相关信息;
- DataBindingInfo.class:一个看似空的类,但在SOURCE阶段包含了一个@BindingBuildInfo注解,包含了基本DataBinding的基本信息;
- DataBindingComponent.class:会根据自定义的DataBindingComponent自动生成对应实例化方法;
- ViewDataBinding.class的子类;
- BR.class;
- DataBindingMapper.class:用于寻找某个layout.xml对应的ViewDataBinding类;
- 流程
- 资源处理
- aapt/gradle-api阶段,都会触发资源处理,DataBinding都会扫描一遍现有的资源,生成不包含<layout>的data-binding-layout-out以及DataBinding所需要的data-binding-info;
- 生成DataBindingInfo.class
- 资源处理后,aapt/gradle-api都会去生成DataBindingInfo.class,把相关的信息写入DataBindingInfo.class的@BindingBuildInfo注解中;
- 监听到注解变化
- 生成@BindingBuildInfo注解,或者code中发现有新的注解写入,AbstractProcessor注解处理器就开始执行注解处理;DataBinding中有一个ProcessDataBinding.java类专门来处理DataBinding相关的注解;
- ProcessDataBinding处理注解,生成bin
- ProcessDataBinding中处理注解永远会按顺执行3步,ProcessMethodAdapter,ProcessExpressions,ProcessBindable。每次执行都会从磁盘反序列化对应的bin文件,然后往bin中写入新的,完成后再序列化到磁盘;
- 生成最终产物
- 执行ProcessMethodAdapter生成DataBindingComponents.class;执行ProcessExpressions生成ViewDataBinding.class子类(ActivityDetail2Binding.class),并触发DataBindingMapper.class更新;执行ProcessBindable生成BR.class,并触发DataBindingMapper.class更新;
验证
- gradle版本使用的是
com.android.tools.build:gradle:3.5.3
;
- 中间产物
- ./build/intermediates/data-binding/debug/bundle-bin目录
- 包含两个文件:module-br.bin和module-setter_store.json;
- 第一个文件应该是用来生成该module对应的br文件;第二个文件记录了该module中所有绑定注解的相关信息(比如,BindingAdapter关联的属性名,View类型,参数类型,以及该方法所属的类);
- ./build/intermediates/data_binding_dependency_artifacts/debug/dataBindingMergeDependencyArtifactsDebug/out目录
- 包含两类文件module-br.bin和module-setter_store.json;文件内容同上;
- ./build/intermediates/data_binding_base_class_log_artifact/debug/dataBindingGenBaseClassesDebug/out目录
- 包含一个文件module-binding_classes.json;包含从XML名称到ViewDataBinding类的映射关系(包括XML中变量类型);
- ./build/intermediates/data_binding_base_class_log_dependency_artifacts/debug/out目录
- 包含依赖module,依赖库的binding_class.json文件,文件内容同上;
- ./build/intermediates/data_binding_layout_info_type_merge/debug/mergeDebugResources/out目录
- 包含了XML中变量部分以及绑定表达式信息,不包含View信息;
- 最终产物
- BR文件
- 包含变量名和属性名(@Bindable注解过的getter方法)对应的ID;
- Binding/BindingImp文件
- XML文件对应的绑定类,实现了运行时自动更新UI的逻辑;
- DataBindingComponent文件
- 如果BindingAdapter注解在实例方法上,会在该接口中生成获取该实例的接口方法;
- DataBinderMapperImpl文件
- 包含了layout对应的id到Binding类的映射,XML的rootView的tag到layout的id的映射,BR中的id到属性名的映射;
总结
- 网上资料和验证结合来看,整体流程没什么变化,除了一些细小的差别(比如Binding类又多了BindingImp子类);
- 流程
- 开发阶段:主要涉及两部分,XML(layout和data标签)和注解;
- 资源处理:将XML拆分成两部分:一部分为layout文件,最终打包到apk中的layout文件,和传统写法差不多,唯一不一样的就是相关View的Tag会改成binding格式,这个是编译期和运行时的纽带;另外一部分是layout-info文件,包括变量和绑定表达式相关信息;
- 注解处理:先处理绑定注解(除Bindable)生成setter_store.json文件;再根据layout-info文件和setter_store.json文件处理绑定表达式,生成Binding/DataBindingComponent文件;再处理Bindable注解,生成BR文件;再生成BindingImp文件(这个是个人猜测,因为BindingImp的逻辑是要根据BR值生成dirtyFlag);再生成DataBinderMapperImpl文件;
存疑
- DataBindingInfo文件及BindingBuildInfo注解有什么用?
- DataBindingComponent不建议使用,在实例方法上注解BindingAdapter,还不如直接在对应的Activity中对可观察数据源挂监听做特殊逻辑;
本文标题:Android-DataBinding-原理-编译期
本文链接:https://www.haomeiwen.com/subject/xmfcfhtx.html
网友评论