DataBinding源码浅析---初始化过程

作为Google官方发布的支持库,DataBinding实现了UI组件和数据源的双向绑定,同时在Jetpack组件中,也将DataBinding放在了Architecture类型之中。对于DataBinding的基础使用请先翻阅前两篇文章的详细阐述。本文所用代码也是建立在之前工程基础之上。

初始化分析

按照官方文档所说,Databinding在编译期会生成代码,利用的技术是Apt(annotation-processing-tool)。在运行完工程后,可以看到build文件夹下生成多个文件夹和文件,看到了这里,就可以明白其核心原理肯定跟注解处理器有关系,其实所有通过APT生成代码的框架(比如ButterKnife,dagger2,hit等),大多数情况下其核心逻辑的实现都在生成代码中,可以说其完全就是通过注解处理器产生的,因此需要我们重点翻阅的都是生成的代码。在我们按照规则写完布局文件后,会生成相应的.java文件,文件名为xml文件名加上Binding后缀。原工程则生成是的ActivityMainBinding.java文件,这点不难理解。

从XML开始

让我们关注build目录下的intermediates目录,你会发现,相较于其他没有使用Data Binding的工程,这里多了几个目录:

image.gif
不难猜出,这是DataBinding特有的目录风格。我们看到最后一个文件夹,展开会发现:

image.gif
这里的activity_main-layout.xml像极了我们activity所使用布局。点开会发现里面充满了各种标签。(如果一开始里面代码只有一行,则可以使用快捷键 Windows : ctrl+Alt + L调整代码格式)

image.gif

先列出原布局文件:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"xmlns:app="http://schemas.android.com/apk/res-auto"><data><import type="com.example.dbjavatest.bean.DataBean"/><variablename="dataInfoBean"type="DataBean" /></data><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:id="@+id/tv_data"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="26sp"android:textColor="@color/purple_200"android:text="@{dataInfoBean.dataInfo}"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"android:layout_marginLeft="50dp"/><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:hint="请输入数据"android:text="@={dataInfoBean.dataInfo}"app:layout_constraintTop_toBottomOf="@+id/tv_data"android:textSize="25sp"android:layout_marginTop="30dp"android:paddingLeft="20dp"/></androidx.constraintlayout.widget.ConstraintLayout>
</layout>

可以看出这里面总共三个控件,对应activity_main-layout.xml中有三个< target>节点。

image.png
节点里view属性名称则刚好可以是我们布局中所用控件,这里就是我们在布局中声明的控件无疑。在这些< target>信息中,还可看到所赋予的tag信息(binding_1、binding_2)。而在Expression标签中,text对应属性值里有“dataInfoBean.dataInfo”这就刚好对应上数据来源。当然,仅仅靠这个文本,是不可能生成一个能绘制出来的效果。这时还要观察另外一个文件。

在intermediates/incremental目录下,相应的有效文件夹为mergeDebugResources\stripped.dir\layout 下,对应的文件名即为布局文件名:
image.gif
点开后你会发现,相较于原始的activity_main.xml布局文件,< layout>和< data>标签都消失了:

image.png
且内部控件都多了一个属性,android:tag属性。此tag属性所赋id则跟build/intermediates/data_binding_layout_info_type_package/debug/out/activity_main-layout.xml中的标签里的tag相对应。不难猜出,其xml具体显示流程与这俩文件紧密相关。

接下来就要去看整体的流程了。

初始化流程

要分析整体流程还得从MainActivity入手,DataBindingUtil.setContentView(this, R.layout.activity_main);就是完成XML布局的初始化操作:

image.png
点进去查看其源码:

image.gif

image.gif
可以发现这里通过获取Window的decorView,来把传进来的layoutId(即我们的布局)通过bindToAddedViews()绑定到屏幕视图上。这里的contentView和其id.content是工程创建时Activity就自带的默认FrameLayout,对这个不了解的要去了解下屏幕渲染机制,在这里不需要纠结。

继续观察bindToAddedViews()内部对于绑定的过程实现:

image.gif
可看到最终都是调用的bind():

image.gif
这其中有个变量,sMapper。我们看到声明地方:

image.gif
可以看到此变量是由一个生成类new出来,且此类并不是原先就存在,只有在编译过程结束后才生成出来的文件:

image.gif
而在此类中最重要的就是getDataBinder(),在此方法中,可以看到拿标签流程:

image.png
通过判断是activity_main.xml的id来返回一个new ActivityMainBindingImpl(component, view);对象。我们点进去观察此对象源码:

源码图片1.png

可以看出,对应取控件id等操作来源得看mapBindings内部实现:

源码图片2.png
源码图片3.png
此方法后续逻辑基本上都是如此,在这方法体内将所有view存进一个数组,然后在ActivityMainBindingImpl中通过bindings[1]去获取view实例:
源码图片4.png
然后通过invalidateAll()更新所有UI。

以上不难看出这些流程就是XML布局的初始化所有流程。在初始化结束后,xml的控件信息就存在了DataBinding对象里,就可以通过DataBinding对象拿到具体对应控件对象实例了。

ActivityMainBinding viewDataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
viewDataBinding.tvData.setText("拿到对象实例了");

这也正是为什么DataBinding可以不用findViewById了的原因。其实不难想到,随着页面的UI复杂度的增加,dataBinding对内存的消耗也会越大,个人感觉这是DataBinding的缺点。(后面有时间,我会去对比DataBinding与常规架构所构建的APP在内存和整体性能上的区别)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/465950.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络报文处理流程

报文处理流程 WLAN网络中的数据包括管理报文和业务数据报文。管理报文必须采用CAPWAP隧道进行转发&#xff0c;而业务数据报文除了可以采用CAPWAP隧道转发之外&#xff0c;还可以采用直接转发方式和Soft-GRE转发方式。 管理报文用来传送AC与AP之间的管理数据&#xff0c;存在于…

反应式编程

反应式编程 前言1 反应式编程概览2 初识 Reactor2.1 绘制反应式流图2.2 添加 Reactor 依赖 3.使用常见的反应式操作3.1 创建反应式类型3.2 组合反应式类型3.3 转换和过滤反应式流3.4 在反应式类型上执行逻辑操作 总结 前言 你有过订阅报纸或者杂志的经历吗?互联网的确从传统的…

BYTEVALUE 百为流控路由器远程命令执行漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

JavaWeb:SpringBootWeb登录认证 --黑马笔记

1.登录认证 登录认证&#xff0c;如果只是简单的判断用户名和密码在数据库中是否对应相等来实现这个需求是有问题的&#xff0c;它只是徒有其表&#xff0c;我们不登陆也可以访问后端系统页面&#xff0c;真正的登录功能应该是&#xff1a;登陆后才能访问后端系统页面&#xf…

Python - 面向对象编程 - 类变量、实例变量/类属性、实例属性

什么是对象和类 什么是 Python 类、类对象、实例对象 类变量、实例变量/类属性、实例属性 前言 只是叫法不一样 实例属性 实例变量 类属性 类变量 个人认为叫属性更恰当 类属性和实例属性区别 类属性&#xff0c;所有实例对象共享该属性实例属性&#xff0c;属于某一…

数据库恢复

文章目录 前言一、事务1.概念2.定义语句3.ACID特性 二、数据库恢复的必要性1.为什么要进行数据库恢复2.数据库恢复机制的作用 三、数据恢复使用的技术1.数据转储2.登记日志文件 四 、不同故障的数据恢复策略1.事务内部的故障2.系统故障3.介质故障 五、具有检查点的恢复技术1.检…

跟着pink老师前端入门教程-day24

四、移动端WEB开发之响应式布局 1、响应式开发 1.1 响应式开发原理 就是使用媒体查询针对不同宽度的设备进行布局和样式的设置&#xff0c;从而适配不同设备的目的。 1.2 响应式布局容器 响应式需要一个父级做为布局容器&#xff0c;来配合子级元素来实现变化效果。 原理…

springboot181基于springboot的乐享田园系统

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

CSS基础---新手入门级详解

CSS:层叠样式表 CSS&#xff08;Cascading Style Sheets,层叠样式表&#xff09;&#xff0c;是一种用来为结构化文档添加样式&#xff08;字体、间距和颜色&#xff09;的计算机语言&#xff0c;css扩展名为.css。 实例: <!DOCTYPE html><html> <head><…

通过容器化释放云的力量

NCSC (英国国家网络安全中心) 经常被问到的一个问题是是否在云中使用容器。这是一个简单的问题&#xff0c;但答案非常微妙&#xff0c;因为容器化的使用方式有很多种&#xff0c;其中一些方法比其他方法效果更好。 今天&#xff0c;我们发布了有关使用容器化的安全指南&#…

C++ //练习 5.19 编写一段程序,使用do while循环重复地执行下述任务:首先提示用户输入两个string对象,然后挑出较短的那个并输出它。

C Primer&#xff08;第5版&#xff09; 练习 5.19 练习 5.19 编写一段程序&#xff0c;使用do while循环重复地执行下述任务&#xff1a;首先提示用户输入两个string对象&#xff0c;然后挑出较短的那个并输出它。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#x…

没更新的日子也在努力呀,布局2024!

文章目录 ⭐ 没更新的日子也在努力呀⭐ 近期的一个状态 - 已圆满⭐ 又到了2024的许愿时间了⭐ 开发者要如何去 "创富" ⭐ 没更新的日子也在努力呀 感觉很久没有更新视频了&#xff0c;好吧&#xff0c;其实真的很久没有更新短视频了。最近的一两个月真的太忙了&#…