参考博文:
https://www.jianshu.com/p/076c0ea32701
https://www.jianshu.com/p/63b514a9d8ea
https://blog.csdn.net/qq_17338093/article/details/53185950
https://www.jianshu.com/p/ab9f1f937e5c
由DataBindingUtil.setContentView
开启源码分析之旅
目录
核心类
DataBindingUtil
DataBindingUtil.setContentView
->
sMapper.getDataBinder
sMapper指向的是AP技术自动生成的Java类-DataBinderMapperImpl
AP生成的类
DataBinderMapperImpl (androidx.databinding目录下)
位置:androidx.databinding.DataBinderMapperImpl
package androidx.databinding;
public class DataBinderMapperImpl extends MergedDataBinderMapper {
DataBinderMapperImpl() {
addMapper(new com.lib.lyskinsupport.DataBinderMapperImpl());
}
}
可以看到androidx.databinding下的DataBinderMapperImpl在自动生成的时候,会在构造方法里添加应用包名下的DataBinderMapperImpl类。
DataBinderMapperImpl (应用包名目录下)
位置:com.lib.lyskinsupport.DataBinderMapperImpl
那么,有两个问题:
第一:view.getTag是什么鬼?
第二:View对应的DataBinding类是怎么自动生成的?
自动生成xml
在编译过程中,databinding会把xml拆分为两部分,数据部分和布局部分。
- 布局部分
databinding会在build/intermediates/incremental/mergeDebugResources/stripped.dir/layout
目录下自动生成传统的xml文件,和布局文件同名。如果是普通布局,则会生成和普通布局源文件一模一样的文件;如果是<layout></layout>
作为根结点的databinding类布局,布局中使用了databinding的View,会自动生成tag属性,其中根结点的tag命名为layout/布局xml文件名_0
,其它的view的tag自上而下命名为binding_1、binding_2
...等等。
形如:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent" android:tag="layout/keyboard_layout_0" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:id="@+id/name"
.....
android:tag="binding_1" />
<ImageView
.......
android:tag="binding_2" />
<TextView
.......
android:tag="binding_3" />
<TextView
.......
android:tag="binding_4"
....../>
<TextView
........
android:tag="binding_5"
......./>
<TextView
.........
android:tag="binding_6" />
</RelativeLayout>
- 数据部分
在build\intermediates\data_binding_layout_info_type_merge\debug\out
目录下会生成数据部分的xml文件,布局源文件名-layout
命名。
形如:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Layout directory="layout" filePath="app\src\main\res\layout\activity_db.xml"
isBindingData="true" isMerge="false" layout="activity_db"
modulePackage="com.lib.lyskinsupport" rootNodeType="android.widget.LinearLayout">
<Variables name="model" declared="true" type="com.lib.lyskinsupport.viewmodel.DbViewModel">
<location endLine="11" endOffset="64" startLine="9" startOffset="8" />
</Variables>
<Imports name="SkinR" type="com.lylib.skin.main.resource.SkinCompatResources">
<location endLine="7" endOffset="69" startLine="5" startOffset="8" />
</Imports>
<Targets>
<Target tag="layout/activity_db_0" view="LinearLayout">
<Expressions>
<Expression attribute="android:background" text="model.rootBackground">
<Location endLine="20" endOffset="51" startLine="20" startOffset="8" />
<TwoWay>false</TwoWay>
<ValueLocation endLine="20" endOffset="49" startLine="20" startOffset="30" />
</Expression>
</Expressions>
<location endLine="82" endOffset="18" startLine="14" startOffset="4" />
</Target>
<Target tag="binding_1" view="LinearLayout">
<Expressions>
<Expression attribute="android:background" text="model.rootBackground">
<Location endLine="30" endOffset="55" startLine="30" startOffset="12" />
<TwoWay>false</TwoWay>
<ValueLocation endLine="30" endOffset="53" startLine="30" startOffset="34" />
</Expression>
</Expressions>
<location endLine="81" endOffset="22" startLine="24" startOffset="8" />
</Target>
<Target tag="binding_2" view="TextView">
<Expressions>
<Expression attribute="android:background"
text="1 > 0 ?@color/main_txt_bg:@color/main_txt_bg">
<Location endLine="72" endOffset="83" startLine="72" startOffset="16" />
<TwoWay>false</TwoWay>
<ValueLocation endLine="72" endOffset="81" startLine="72" startOffset="38" />
</Expression>
<Expression attribute="android:textColor"
text="1 > 0 ? @color/main_bg : @color/main_txt">
<Location endLine="74" endOffset="78" startLine="74" startOffset="16" />
<TwoWay>false</TwoWay>
<ValueLocation endLine="74" endOffset="76" startLine="74" startOffset="37" />
</Expression>
</Expressions>
<location endLine="75" endOffset="41" startLine="69" startOffset="12" />
</Target>
<Target id="@+id/tv_cur_skin_info" view="TextView">
<Expressions />
<location endLine="37" endOffset="54" startLine="34" startOffset="12" />
</Target>
</Targets>
</Layout>
这两个xml文件,databinding相关的编译器是如何自动生成的呢?
这个涉及到databinding编译原理,比较复杂,可以参照:http://xinyiworld.top/wordpress/?p=5130
自动生成Binding相关的Java类
一个databinding布局xml文件,会生成一系列的binding类。假如这个布局文件为activity_db.xml
ActivityDbBinding
生成ViewModel的get方法及抽象的set方法
ActivityDbBindingImpl
->executeBindings:进行数据与View的绑定
父类ViewDataBinding有3个方法获取资源getColorFromResource、getColorStateListFromResource、getDrawableFromResource
- 对于textColor属性
调用ViewDataBinding的getColorFromResource方法将colorRes转化成colorInt,然后setTextColor(@ColorInt int color)
设置给View。 - 对于background属性
1)如果设置的是colorRes,会通过ViewDataBinding的getColorFromResource
将colorRes转化成colorInt,然后通过androidx.databinding.adapters.Converters.convertColorToDrawable
将colorInt转化成drawable,最后通过androidx.databinding.adapters.ViewBindingAdapter.setBackground
将drawable设置给View。
2)如果设置的是colorInt,会通过androidx.databinding.adapters.Converters.convertColorToDrawable
将colorInt转化成drawable,最后通过androidx.databinding.adapters.ViewBindingAdapter.setBackground
将drawable设置给View。
3)如果设置的是drawable,会直接通过androidx.databinding.adapters.ViewBindingAdapter.setBackground
将drawable设置给View。
0 条评论