在 android 文档中,我们有没有
lateinit
的视图绑定示例:
private var _binding: ResultProfileBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
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
}
为什么我们不使用
lateinit
,就像我们在 Activity 中使用它一样:
private lateinit var binding: ResultProfileBinding
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = ResultProfileBinding.inflate(inflater, container, false)
return binding.root
}
我怀疑它有内存泄漏问题。能解释一下吗?
我找到了一个很好的解释这里。
解释片段:
碎片中如何发生泄漏?首先,我们需要先回顾一下 片段的重要细微差别。它们有两个不同的生命周期:
- 它有自己的生命周期(
和onCreate
)onDestroy
- 它是视图的生命周期(
和onCreateView
)onDestroyView
单个有两个生命周期 屏幕可能有问题。它们的创建和销毁时间不同 例如,将片段放在返回堆栈上时。 具体来说,在调用
后保留视图将 泄露。当片段位于返回堆栈上时会发生这种情况,尽管 它的视图被破坏了,但片段本身却没有。垃圾 收集器无法清除对这些视图的引用。onDestroyView
还有来自this Stack Overflow 答案的一个片段:
您必须取消对
中视图的引用,如下所示 这是该视图不再被 Fragment 使用的标志 系统,如果不适合您,它可以安全地被垃圾收集 继续参考onDestroyView
。View
binding
未设置为 null,则可能会导致内存泄漏。这就是为什么我们在 onDestroyView
中将
_binding
设置为
null
在使用 onDestroyView
时,我们无法将
lateinit
属性分配给 lateinit
。因此,如果我们使用 null
,我们将无法在 lateinit binding
中将其设置为 null,并且会导致 onDestroyView
。这就是为什么 Android 文档建议使用 memory leak
变量。在 nullable
的情况下,我们不需要将
activities
分配给 binding
,因为它们不会导致内存泄漏,并且我们可以为 null
使用 lateinit
属性。binding
如果用户在收到文档之前打开片段并关闭它(这意味着片段不再被使用,并且如果变量为空或不再使用,则应通过垃圾收集器清除其所有变量)
现在让我们讨论一下场景
// here a firestore database uses callback to be executed when the document recieved
db.collection("cities").document("SF").get()
.addOnSuccessListener { document ->
if (document != null) {
binding.textView.text = document.data.toString()
} else {
Log.d(TAG, "No such document")
}
}
lateinit
车库收集器不会清除
private lateinit var binding: ResultProfileBinding
,因为它仍在回调中使用,并且片段将保留在内存中,这会导致内存泄漏,但是回调执行并设置用户不会知道的文本,因为他留下了片段
想象一下,如果用户多次执行此场景!!那么可为 null 的绑定又如何呢?
binding
您在
private var _binding: ResultProfileBinding? = null
private val binding get() = _binding!!
中将其设置为 null,以便
onDestroyView
和片段可以被垃圾收集(无内存泄漏)但是当回调执行时会发生什么?
您会得到一个
binding
,所以请注意这一点
无论用户打开片段并关闭它多少次,它都会被垃圾收集尝试使用此代码,您可以使用
Android Studio Profiler来查看设备内存和/或 leakCanary 来获取有关应用程序内存泄漏的通知