为什么Fragment实现View Binding时私有binding属性需要加get()?
Kotlin自定义getter在ViewBinding场景的作用
Kotlin的属性分为两种声明方式:带默认幕后字段的存储属性、带自定义get()的计算属性。你代码里的get()就是用来声明计算属性的关键字,它的特性是:每次访问该属性时,都会执行get()代码块中的逻辑,返回最新的计算结果,而不会提前存储固定值。
对应你的代码场景:
private val binding get() = _binding!!
每次你调用binding访问视图时,都会读取当前_binding的最新值再做非空强转,而不是读取初始化时的固定值。
官方提到的「只读」特性有两层含义:
binding本身用val声明,没有自定义setter,你无法直接给binding重新赋值binding的返回值完全由_binding的当前值决定,你只能通过修改_binding来改变binding的返回结果,无法直接修改binding本身的取值逻辑
直接赋值写法的问题
如果你写成private val binding = _binding!!,这属于存储属性的声明,赋值逻辑会在Calculator类实例初始化阶段就执行,将当时的_binding值强转后存入幕后字段,后续所有对binding的访问都会读取这个初始化时固定的结果,不会再同步_binding的最新值,会直接触发以下问题:
- 初始化直接崩溃:Fragment类实例创建的时候,
_binding还没有被赋值(ViewBinding的初始化要到onCreateView生命周期才会执行),此时_binding为null,!!强转直接抛出NullPointerException,页面无法启动 - 即便你绕过了初始化阶段的赋值,后续生命周期变化时也会出现异常:Fragment的View销毁时我们通常会把
_binding置为null避免内存泄漏,此时直接赋值的binding还是持有旧的Binding实例,访问时会用到已经销毁的视图,导致内存泄漏、页面触摸无响应等异常问题
两种写法的核心差异对比:
- 带
get()的计算属性:仅在实际访问binding时才会取值,永远返回_binding的最新状态,符合Fragment生命周期的变化要求 - 不带
get()的存储属性:类初始化时就固定取值,完全不匹配ViewBinding的赋值时机,必然出现运行时异常
内容的提问来源于stack exchange,提问作者user16537655
相关产品推荐
相关产品推荐

