以下两种方法有什么区别或没有区别:
1.
private lateinit var binding: ResultProfileBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ResultProfileBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
}
private var _binding: ResultProfileBinding? = null
// This property is only valid between onCreateView and onDestroyView.
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
_binding = ResultProfileBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
}
以上示例代码来自:https://developer.android.com/topic/libraries/view-binding 。一种对 Activity 使用 lateinit,另一种对 Fragment 使用由可选 var 支持的计算属性。
两者似乎都可以在 Fragment 和 Activity 中使用,但这让我很好奇:Kotlin 语言有什么区别吗?
最佳答案
他们为 Fragment 示例执行此操作的原因是,Fragment View 在与 Activity 分离时可能会被拆除并删除,然后在同一个 Activity 上重新创建(在 onCreateView()
中)重新附加到 Activity 时的 fragment 实例。在 Fragment 分离期间,原始绑定(bind)实例无效,因此使用可为 null 的属性 (_binding
),并在 onDestroyView()
中将其设置回 null 值(请参阅您链接的示例代码)以避免在这些 View 不再有效时泄漏它们。
但在 Fragment 代码的大多数地方,可以安全地假设 Fragment 已附加,因此返回非空绑定(bind)的 binding
属性是为了方便起见。这类似于 requireContext()
和 requireActivity()
,它们比可为空的 context
和 activity
使用起来更方便。您只需要避免在 fragment 可能分离时使用它们即可。这可能会发生在异步代码中,例如某些网络调用的回调中。
在 Activity 中,它们使用 lateinit
因为在 Activity 完全构造之前无法初始化 View 。您的第一个安全入口点是 onCreate()
,因此可以在那里设置该属性。 lateinit
允许属性不可为 null,但只要您尽早设置其初始值(即 onCreate()
),就可以安全使用。
lateinit
对于 Fragment 来说不是正确的方法,因为在 Fragment 生命周期的某些时间内,绑定(bind)实际上不存在,因此您需要能够将其设置为 null。对于 Activity,您可以选择使用可为 null 的属性而不是 lateinit
,但在您有权访问 Activity 成员期间,如果它永远不可能为 null,则必须处理其可为 null 性是不切实际的.
关于android - kotlin Lateinit 与计算属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66751722/