1.启动流程
在 build.gradle
中启用:
android {
dataBinding {
enabled = true
}
}
这会让编译器为每个布局文件生成对应的绑定类(如 ActivityMainBinding
、DetailsFragmentBinding
)。
2. 布局文件转换
将普通布局文件转换为 DataBinding 布局,需要在根标签外包裹
标签:
1.绑定基本数据对象
data class User(
var name: String,
var age: Int
)
在 Activity 中设置绑定
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 使用 DataBindingUtil 生成的 Binding 类(Kotlin 语法)
val binding = DataBindingUtil.setContentView(
this, R.layout.activity_main
)
// 创建数据对象
val user = User("John Doe", 25)
// 设置数据对象到绑定类
binding.user = user
}
}
2.事件绑定
绑定点击事件(布局文件)
在 ViewModel 中处理事件
class MyViewModel {
fun submit() {
// 处理提交逻辑
}
}
自定义 Data Binding 逻辑的核心是 @BindingAdapter
注解。这个注解用于类中的静态方法(在 Kotlin 中通常是 companion object
,使方法成为静态),以定义可在 XML 布局文件中使用的自定义属性。
setMediaSourceInfo
、setMediaSourceRightButton
)这些适配器展示了 Data Binding 最简单的用法:
@BindingAdapter("media_source_icon", "media_source_name")
@JvmStatic
fun setMediaSourceInfo(view: MediaSourceBar, drawable: Drawable?, name: String?) {
name?.let { view.setMediaSourceName(it) }
drawable?.let { view.setMediaSourceIcon(it) }
}
在XML 中,你可以这样使用:
这直接根据 Drawable
和 String
数据在自定义 MediaSourceBar
视图上设置属性。
2.将数据绑定到 RecyclerView
(bindRecyclerView
)
这是 Data Binding 的常见而强大的应用。你无需在 Fragment 或 Activity 中手动设置适配器和提交列表,Data Binding 会处理这些:
@BindingAdapter("data")
@JvmStatic
fun bindRecyclerView(
recyclerView: Recyclerview,
list: MutableList?,
) {
val adapter = recyclerView.adapter
if (adapter is RecyclerViewListAdapter) {
list?.let { adapter.submitList(it) }
}
}
这里,data
属性与 RecyclerView
一起使用。适配器检查现有的 recyclerView.adapter
是否是特定类型(RecyclerViewListAdapter
),然后调用其 submitList
方法,很可能使用 DiffUtil
进行高效更新。 XML 用法:
bindMediaMetadataInfo
、bindMediaMetadataProgress
、bindMediaMetadataCommands
)这些适配器展示了如何传递自定义对象和多个相关属性:
@BindingAdapter(value = ["media_metadata", "media_source"], requireAll = false)
@JvmStatic
fun bindMediaMetadataInfo(
simpleMediaView: PlayInfoView,
mediaMetadata: MediaMetadata?,
mediaSource: ServiceBean?
) {
simpleMediaView.setMediaMetadata(mediaMetadata)
// 基于 mediaSource 的条件逻辑
if (mediaSource?.packageName == MediaBrowserManager.NETEASE_PACKAGE_NAME) {
simpleMediaView.setMediaServiceBean(mediaSource)
} else {
simpleMediaView.setMediaServiceBean(null)
}
}
PlayInfoView
会使用 MediaMetadata
和 ServiceBean
对象进行更新。条件逻辑 (if (mediaSource?.packageName == MediaBrowserManager.NETEASE_PACKAGE_NAME)
) 表明你可以在绑定适配器中直接嵌入业务逻辑,根据数据决定如何更新视图。
4.条件 UI 更新和资源更改(isPlaying
)
isPlaying
适配器是基于布尔状态动态更改 UI 的一个很好的例子:
@BindingAdapter("isPlaying", requireAll = false)
@JvmStatic
fun bindMediaMetadataPlayback(
view: View,
isPlaying: Boolean?,
) {
if (view is PlayInfoView) {
view.setPlayback(isPlaying)
}
if (view is tech.jidouauto.component.widgets.basic.ImageView) {
if (isPlaying == true) {
view.setImageResource(com.jidouauto.mediacenter.R.drawable.item_icon_pause)
} else {
view.setImageResource(com.jidouauto.mediacenter.R.drawable.item_icon_play)
}
}
}
这个适配器智能地处理不同的 View
类型。如果视图是 PlayInfoView
,它会调用 setPlayback
。如果它是 ImageView
,它会更改图像资源为播放或暂停图标,将此逻辑从你的 Activity/Fragment 中移除。
image_corners_uri
、image_cycle_uri
、player_album_image_cover
)这些适配器封装了复杂的图片加载逻辑:
@BindingAdapter("image_corners_uri", "image_radius", requireAll = false)
@JvmStatic
fun imageUri(view: tech.jidouauto.component.widgets.basic.ImageView, uri: Any?, radius: Int?) {
uri?.let {
val imageResource = ImageResource.Remote(
uri,
transformationType = IImageLoader.ImageTransformationType.RoundCorners(radius?.dp ?: 24.dp),
placeholder = com.jidouauto.mediacenter.R.drawable.icon_placeholder,
error = com.jidouauto.mediacenter.R.drawable.icon_placeholder
)
view.imageSource = imageResource
}
}
这些适配器不是直接在代码中调用图片加载库(如 Glide 或 Picasso),而是定义自定义属性(image_corners_uri
、image_radius
、image_cycle_uri
、player_album_image_cover
),这些属性处理设置带有特定转换(圆角、圆形裁剪)、占位符和错误图片的图像源。这使得你的 XML 干净,代码分离。
6.将数据绑定到自定义视图(banner_data
)
这演示了将复杂数据对象绑定到完全自定义的视图:
@BindingAdapter("banner_data", requireAll = false)
@JvmStatic
fun bindBannerViewData(
view: TopBannerCarouselPager,
data: MainBannerItem?,
) {
Logger.info("bind main banner data=${data?.items}")
if (data == null) return
view.setAdapter(TopBannerCarouselPager.Adapter(data.items, data.itemOnClick))
}
TopBannerCarouselPager
自定义视图直接接收 MainBannerItem
对象,适配器使用提供的数据和点击处理程序设置其内部适配器。
四、整体总结
DataBinding 的使用需先在 build.gradle 中启用,将布局文件用
通过创建数据模型,在 Activity 中利用 DataBindingUtil 设置布局并绑定数据对象,还可在布局中绑定 ViewModel 的事件方法;其核心自定义逻辑在于 @BindingAdapter 注解,可用于静态方法定义自定义属性,实现多种功能,如设置视图基本属性、将数据绑定到 RecyclerView、处理多个属性和复杂对象、根据条件更新 UI、进行图片加载的自定义转换以及将数据绑定到自定义视图等,能让 XML 更简洁,实现代码分离。