非空LiveData为何返回null?空指针异常问题排查
场景代码
Fragment中订阅LiveData:
vm.fieldsValidated.observe(viewLifecycleOwner){ enableContinueButton(it) //<----- line 116 }
ViewModel中的LiveData声明:
protected val _fieldsValidated = MutableLiveData<Boolean>() val fieldsValidated: LiveData<Boolean> = _fieldsValidated
enableContinueButton方法要求接收非空Boolean参数:
fun enableContinueButton(state: Boolean) { ... }
崩溃信息
Location: MyFile.kt line 116 in MyFragment$setupObservers$2.invoke
Exception: java.lang.NullPointerException
Message: it must not be null
原因解析
虽然Kotlin代码里把LiveData<Boolean>声明为非空类型,但运行时仍会出现null值,核心原因有两个:
LiveData初始值默认是null:
MutableLiveData<Boolean>()如果没有显式设置初始值,内部默认值就是null。LiveData是Java实现的组件,Java泛型不区分可空与非空,Kotlin的非空注解仅做编译期检查,无法在运行时阻止LiveData持有null。当Fragment开始订阅时,如果还没通过setValue或postValue设置有效值,会立即收到这个null初始值,传给要求非空参数的enableContinueButton后触发空指针异常。存在绕过Kotlin非空检查的代码:如果项目中有Java代码调用ViewModel里的
_fieldsValidated,调用setValue(null)或postValue(null)时,Java不会识别Kotlin的非空约束,能直接传入null。另外,若使用反射等非常规手段修改LiveData的值,也可能导致null被传入。
解决方案
- 给LiveData设置非空初始值:
protected val _fieldsValidated = MutableLiveData<Boolean>(false)
- 在Observer中添加空值兜底逻辑:
vm.fieldsValidated.observe(viewLifecycleOwner){ it -> enableContinueButton(it ?: false) }
- 排查所有设置
_fieldsValidated值的代码,确保没有传入null的情况,重点检查Java代码和反射调用场景。
内容的提问来源于stack exchange,提问作者Sirop4ik

