9、DataBinding资源引用:引用String资源、引用Dimen资源、引用Color资源、引用Plurals复数资源
各位同学,咱们今天聊点实在的。DataBinding 除了绑定数据,还有一个很实用的功能——直接引用 Android 资源文件。说白了,就是你在布局文件里就能拿到 strings.xml、colors.xml、dimens.xml 里的值,甚至还能处理复数资源。这功能我刚开始用的时候觉得挺新鲜,后来发现它确实能省不少事。
核心要点:DataBinding 的资源引用机制,让你在 XML 布局中直接使用 @{} 语法引用资源,无需在 Activity 或 Fragment 中手动获取。
9.1 引用 String 资源
先说说最常用的字符串引用。你可能会问:直接在布局里写死字符串不行吗?当然可以,但为了国际化,我们通常把字符串放在 strings.xml 里。DataBinding 让这件事变得特别自然。
我记得第一次在项目里用这个特性时,团队里还有人质疑:“直接在 XML 里写 @string/app_name 不就行了?干嘛要用 DataBinding?” 嗯,区别在于:当你需要拼接字符串、或者根据数据动态显示不同文案时,DataBinding 的 @{} 语法就派上用场了。
<!-- strings.xml -->
<string name="welcome_message">欢迎回来,%s!</string>
<string name="user_count">当前在线用户:%d 人</string>
<!-- activity_main.xml -->
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="userName" type="String" />
<variable name="onlineCount" type="int" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{@string/welcome_message(userName)}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{@string/user_count(onlineCount)}" />
</LinearLayout>
</layout>
看到没?@{@string/welcome_message(userName)} 这种写法,就是把 userName 变量传进字符串占位符里。我个人习惯把这种带参数的字符串引用叫做“智能字符串”,因为它能根据数据自动变化。
小技巧:如果字符串里没有占位符,直接写 @{@string/app_name} 就行。有占位符时,括号里传参数,多个参数用逗号隔开。
9.2 引用 Dimen 资源
尺寸资源在 Android 开发中很常见,比如边距、字体大小、控件宽高。DataBinding 里引用 Dimen 资源,语法和 String 类似,但有个坑——我踩过。
<!-- dimens.xml -->
<dimen name="margin_normal">16dp</dimen>
<dimen name="text_size_title">20sp</dimen>
<!-- 布局文件 -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@{@dimen/margin_normal}"
android:textSize="@{@dimen/text_size_title}"
android:text="Hello World" />
看起来很简单对吧?但注意:Dimen 资源引用返回的是 float 类型,不是 int。我曾经在设置 android:padding 时直接用了 @{@dimen/margin_normal},结果编译报错。为什么?因为 padding 属性期望的是 dimension 类型,而 DataBinding 表达式返回的是 float,需要显式转换。
避坑指南:我曾经在项目里直接写 android:padding="@{@dimen/margin_normal}",结果编译报错。正确做法是:android:padding="@{@dimen/margin_normal}" 其实是可以的,但如果你在自定义属性或某些特殊场景下,可能需要用 @dimen/margin_normal 直接引用,而不是通过 DataBinding 表达式。记住:能用原生 @dimen/xxx 的地方,尽量别用 @{@dimen/xxx},除非你需要动态计算。
9.3 引用 Color 资源
颜色引用也是高频操作。DataBinding 里引用 Color 资源,语法是 @{@color/color_name}。但这里有个细节:返回的是 int 类型的颜色值,不是 ColorDrawable 或 ColorStateList。
<!-- colors.xml -->
<color name="primary">#FF6200EE</color>
<color name="primary_dark">#FF3700B3</color>
<!-- 布局文件 -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="重要提示"
android:textColor="@{@color/primary}"
android:background="@{@color/primary_dark}" />
你想想看,如果不用 DataBinding,你得在 Activity 里写 getResources().getColor(R.color.primary),然后通过 setTextColor() 设置。现在一行代码搞定,是不是清爽多了?
注意:如果你需要引用 ColorStateList(比如按钮在不同状态下的颜色),DataBinding 也支持:@{@color/btn_selector}。但返回的是 ColorStateList 对象,不是 int。
9.4 引用 Plurals 复数资源
复数资源是 Android 里比较特殊的一种资源。它根据数量自动选择单复数形式。比如“1条消息”和“3条消息”,英文里是 “1 message” 和 “3 messages”,中文虽然没这么复杂,但有些场景还是需要的。
我记得在做一个社交应用时,需要显示“xx人赞了这条动态”。1个人时显示“1人赞了”,多人时显示“N人赞了”。用 Plurals 资源配合 DataBinding,简直完美。
<!-- plurals.xml -->
<plurals name="like_count">
<item quantity="one">%d 人赞了</item>
<item quantity="other">%d 人赞了</item>
</plurals>
<!-- 布局文件 -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{@plurals/like_count(likeCount)}" />
等等,这里有个坑。上面这种写法 编译会报错。为什么?因为 @plurals 资源引用需要指定数量参数,但 DataBinding 的语法是 @{@plurals/resource_name(count)},其中 count 是 int 类型变量。但实际使用时,你还需要传入格式化参数。
正确写法是这样的:
<!-- 正确写法 -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{@plurals/like_count(likeCount, likeCount)}" />
第一个 likeCount 是用于选择单复数的数量,第二个 likeCount 是传入占位符 %d 的参数。说白了,就是 第一个参数决定用哪个复数形式,后面的参数用于格式化字符串。
避坑指南:我曾经在这里卡了半小时。如果你只传一个参数,比如 @{@plurals/like_count(likeCount)},编译不会报错,但运行时会显示 %d 人赞了 这样的原始字符串,因为 %d 没有被替换。记住:Plurals 资源引用至少需要两个参数:第一个是数量选择器,后面是格式化参数。
9.5 资源引用综合示例
咱们来个综合的例子,把上面几种资源引用串起来。假设我们要做一个用户信息卡片:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="user" type="com.example.User" />
<variable name="followerCount" type="int" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@{@dimen/margin_normal}"
android:background="@{@color/card_background}">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{@string/welcome_message(user.name)}"
android:textColor="@{@color/primary}"
android:textSize="@{@dimen/text_size_title}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{@plurals/follower_count(followerCount, followerCount)}"
android:textColor="@{@color/secondary_text}"
android:textSize="@{@dimen/text_size_body}" />
</LinearLayout>
</layout>
这个例子展示了:
- String 资源带参数引用
- Dimen 资源用于边距和字体大小
- Color 资源用于文字和背景颜色
- Plurals 资源处理复数文案
你看,一个布局文件就把所有资源引用都覆盖了。不用写一行 Java/Kotlin 代码,UI 就动态展示出来了。我个人觉得,这种写法特别适合 MVVM 架构,ViewModel 只管提供数据,布局文件负责展示,各司其职。
9.6 资源引用知识体系
为了让你更直观地理解 DataBinding 资源引用的全貌,我画了一张图:
这张图把四种资源引用的语法和返回值都列出来了。你写代码时如果忘了,回来看看这张图就行。
9.7 避坑总结
最后,我把这些年踩过的坑总结一下:
| 资源类型 | 常见错误 | 正确做法 |
|---|---|---|
| String | 忘记传参数,导致显示 %s | 有占位符时,括号内传对应参数 |
| Dimen | 在需要 dimension 类型的地方用 float | 能用原生 @dimen/xxx 就用原生 |
| Color | 混淆 int 和 ColorStateList | 普通颜色用 @{@color/xxx},selector 用 @{@color/xxx} |
| Plurals | 只传一个参数,%d 没被替换 | 至少传两个参数:数量 + 格式化参数 |
嗯,关于 DataBinding 的资源引用,今天就聊这么多。这些技巧我在实际项目中反复用过,确实能提升开发效率。你写代码时多试试,很快就能上手。
公众号:蓝海资料掘金营,微信deep3321