提问人:pti4ik 提问时间:5/21/2023 更新时间:5/22/2023 访问量:201
Kotlin 中的 lambda 是否始终引用创建它的对象?
Does lambda in Kotlin always hold reference to the object where it was created?
问:
我有一个关于 kotlin lambda 和对 .让我们看一下这段代码:this
class MyViewModel: ViewModel {
val eventFlow = mutableSharedFlow<Unit>()
}
class MyFragment: Fragment() {
val viewModel = MyViewModel()
val lambda_1: (Unit) -> Unit = { Log.v("TAG", "Event happened") }
val lambda_2: (Unit) -> Unit = { processEvent() }
fun processEvent() {
//do smth
}
override fun onCreate(bundle: Bundle?) {
lifecycleScope.launchWhenStarted {
viewModel.eventFlow.collect(lambda_1)
}
lifecycleScope.launchWhenStarted {
viewModel.eventFlow.collect(lambda_2)
}
}
}
请告诉我我是否正确:
lambda_1
不调用 的任何方法或变量,因此它不保留对对象的引用。MyFragment
MyFragment
lambda_2
从 调用方法,因此它确实保存对对象的引用。MyFragment
MyFrgament
- 如果 2nd 是正确的,那么当使用这样的 lambda 时,我们违反了 MVVM 的一点(“ViewModel 不得引用 View”),因为有一个引用链 -> -> -> 。
viewModel
eventFlow
lambda_2
MyFragment
试图读取字节码,但无法从中找出答案。
答:
5赞
broot
5/22/2023
#1
1. 是的,这是正确的。 不需要引用 ,所以它不保留一个。事实上,由于 可能是完全静态的,因此 Kotlin 编译器会创建一个单例,并为 的所有实例重用相同的实例。lambda_1
MyFragment
lambda_1
MyFragment
2.这也是正确的。 需要引用 ,所以它保留一个。在这种特定情况下,它的工作方式与内部类类似,因此当实例化 lambda 时,它会通过构造函数将引用传递给自身。一般来说,它是不同的,因为 lambda 包含对它需要的任何对象的引用,无论它是否是“外部”类。lambda_2
MyFragment
MyFragment
3. 老实说,我对 MVVM 不是很熟悉,但我认为它的限制与一般的良好做法相同。
a). 如果你关注的是应用架构和关注点的分离,所以下层不应该调用上层,那么这种情况就不违反这个规则了。View 仅在 viewmodel 中注册事件,但 viewmodel 仍然不直接引用视图,也不知道它们。
如果你担心的是实例被泄露了,它不能被垃圾回收,那么在这种特定情况下这不是问题。 收集流量时使用。当片段被销毁时,它会取消所有启动的协程,流收集器也会被取消,因此不再需要 lambda,可以进行垃圾回收。MyFragment
MyFragment
lifecycleScope
lifecycleScope
评论