一、核心概念
viewbinding 是 android jetpack 组件,用于替代传统 findviewbyid,提供类型安全和空安全的视图访问方式。它会在编译时为每个 xml 布局文件生成绑定类,直接映射视图 id。
// 传统方式 vs viewbinding val textview = findviewbyid<textview>(r.id.tv_title) // 传统 binding.tvtitle.text = "hello viewbinding" // viewbinding
二、viewbinding优点
类型安全:自动匹配视图类型,避免类型转换错误
空安全:生成的视图引用永不为 null(除非布局中不存在)
编译时检查:xml-id 错误在编译时暴露,而非运行时崩溃
代码简洁:消除模板代码,提升可读性
性能优化:编译时生成代码,零运行时开销
三、使用流程
1. 启用 viewbinding (模块级 build.gradle)
android { buildfeatures { viewbinding true } }
2. 自动生成的绑定类
布局文件:activity_main.xml
<linearlayout> <textview android:id="@+id/tvheader" /> <button android:id="@+id/btnsubmit" /> </linearlayout>
将生成绑定类:activitymainbinding.java
public final class activitymainbinding { public final textview tvheader; public final button btnsubmit; ... }
3. activity 中使用
class mainactivity : appcompatactivity() { private lateinit var binding: activitymainbinding override fun oncreate(savedinstancestate: bundle?) { super.oncreate(savedinstancestate) binding = activitymainbinding.inflate(layoutinflater) setcontentview(binding.root) // 关键:设置根视图 // 直接访问视图 binding.tvheader.text = "welcome" binding.btnsubmit.setonclicklistener { // 处理点击事件 } } }
4. fragment 中使用
class homefragment : fragment() { private var _binding: fragmenthomebinding? = null private val binding get() = _binding!! // 安全解包 override fun oncreateview( inflater: layoutinflater, container: viewgroup?, savedinstancestate: bundle? ): view { _binding = fragmenthomebinding.inflate(inflater, container, false) return binding.root } override fun ondestroyview() { super.ondestroyview() _binding = null // 防止内存泄漏 } }
5. 自定义视图组件中使用
class customview @jvmoverloads constructor( context: context, attrs: attributeset? = null ) : linearlayout(context, attrs) { private val binding = customviewbinding.inflate( layoutinflater.from(context), this, true ) init { binding.tvlabel.text = "custom component" } }
四、与 databinding 对比
特性 | viewbinding | databinding |
---|---|---|
核心目的 | 视图访问 | 数据绑定 + 视图访问 |
布局变量支持 | ❌ 不支持 | ✅ 支持 |
表达式语言 | ❌ 不支持 | ✅ 支持 |
双向绑定 | ❌ 不支持 | ✅ 支持 |
性能开销 | ⚡️ 零运行时开销 | ⚠️ 有运行时开销 |
启用复杂度 | ✅ 简单 | ⚠️ 需额外配置 |
适用场景 | 纯视图访问 | 数据驱动ui |
五、实践使用
空安全处理:fragment 中使用解包模式
private val binding get() = _binding!!
多模块支持:在公共模块声明通用绑定
interface bindablefragment<b : viewbinding> { val binding: b }
适配器中使用:recyclerview.viewholder 示例
class userviewholder(val binding: itemuserbinding) : recyclerview.viewholder(binding.root) { fun bind(user: user) { binding.tvname.text = user.name } }
包含布局处理:合并 <include>
标签
<include android:id="@+id/toolbar" layout="@layout/toolbar" />
binding.toolbar.tvtitle.text = "home" // 直接访问子视图
六、问题解决方案
场景1:忽略某些布局文件
<linearlayout tools:viewbindingignore="true"> <!-- 在根布局添加 -->
场景2:处理可选视图
<linearlayout tools:viewbindingignore="true"> <!-- 在根布局添加 -->
场景3:兼容旧项目
// 与传统findviewbyid共存 val oldview = findviewbyid<textview>(r.id.legacy_view) binding.modernview.text = "new approach"
七、性能分析
编译时生成:无运行时反射开销
内存占用:绑定对象仅存储视图引用
benchmark 数据:
视图访问速度比 findviewbyid 快 2-3 倍
内存开销比 databinding 低 40%
到此这篇关于android viewbinding 简述的文章就介绍到这了,更多相关android viewbinding 简述内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论