为什么不在 Android Fragment 视图绑定中使用 Lateinit 修饰符?

问题描述 投票:0回答:3

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
}

我怀疑它有内存泄漏问题。能解释一下吗?

android kotlin data-binding fragment
3个回答
4
投票

我找到了一个很好的解释这里

解释片段:

碎片中如何发生泄漏?首先,我们需要先回顾一下 片段的重要细微差别。它们有两个不同的生命周期:

  • 它有自己的生命周期(
    onCreate
    onDestroy
  • 它是视图的生命周期(
    onCreateView
    onDestroyView

单个有两个生命周期 屏幕可能有问题。它们的创建和销毁时间不同 例如,将片段放在返回堆栈上时。 具体来说,在调用

onDestroyView
后保留视图将 泄露。当片段位于返回堆栈上时会发生这种情况,尽管 它的视图被破坏了,但片段本身却没有。垃圾 收集器无法清除对这些视图的引用。

还有来自this Stack Overflow 答案的一个片段:

您必须取消对

onDestroyView
中视图的引用,如下所示 这是该视图不再被 Fragment 使用的标志 系统,如果不适合您,它可以安全地被垃圾收集 继续参考
View


0
投票
如果片段中的

binding
未设置为 null,则可能会导致内存泄漏。这就是为什么我们在
onDestroyView
 中将 
_binding
 设置为 
null
在使用 

onDestroyView

时,我们无法将

lateinit
属性分配给
lateinit
。因此,如果我们使用
null
,我们将无法在
lateinit binding
中将其设置为 null,并且会导致
onDestroyView
。这就是为什么 Android 文档建议使用
memory leak
变量。

nullable

的情况下,我们不需要将

activities
分配给
binding
,因为它们不会导致内存泄漏,并且我们可以为
null
使用
lateinit
属性。
    


0
投票

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 来获取有关应用程序内存泄漏的通知

© www.soinside.com 2019 - 2024. All rights reserved.