我试图理解片段中视图绑定的实现,发现它与活动不同。
在活动中:
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
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = ResultProfileBinding.inflate(inflater, container, false)
val view = binding.root
return view
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
现在我的问题是,为什么我们在片段中有binding
和_binding
?这条线路在做什么?它的目的是什么?
private val binding get() = _binding!!
在第二个示例中,_binding
属性可以为null,以便允许在"初始化"之前的状态。然后,binding
属性有一个getter来提供方便的访问,假设backing字段(_binding
(已经初始化。
您所指的特定行表示,当您尝试访问binding
时,它将返回_binding
。然而,null断言运算符(!!
(添加了_binding
不是null的额外断言。
实际上,您所做的只是创建一个lateinit属性的模拟,实际上,如果您查看lateinit声明的反编译字节码,它们的数量是相同的。
然而,正如@Tenfour04所指出的,这里的细微区别在于,第二种方法允许您将backing字段设置回null,而使用lateinit
属性则无法做到这一点。当您在片段中使用绑定时,建议将onDestroyView
中的绑定置空,以避免内存泄漏,所以这就是他们在片段中采用这种方法的原因。
在片段中,View在onCreateView((方法调用中实例化。但是onCreateView((并不是创建片段时调用的第一个方法,这意味着在onCreateView((方法调用之前,View可能为null,如果View为null,那么_binding属性也将为null。为了避免nullPointerException,我们使用了一个变量";绑定";以获取binding的最新非null(!!checks(值。
private val binding get() = _binding!!
这个声明有一个内置的get()
方法,它在我们对binding
进行的每次调用中更新binding
的值,以返回_binding
的当前非null值,因为如果_binding
有null值,_binding!!
将抛出异常。