移除不必要的val修饰符致Kotlin类Flow订阅失效问题排查
核心问题出在构造参数的生命周期捕获方式上:
OverlaySensorViewModel失效的根源
当你移除构造参数repository的val修饰符后,它就只是构造函数的局部变量——构造函数执行完成后,这个变量没有被ViewModel类持有任何强引用。你的showTimer直接引用的是repository.showTimer,也就是Repository内部MutableStateFlow转换来的SharedFlow。但因为repository本身没有被任何对象持有强引用,会被JVM垃圾回收,连带它内部的MutableStateFlow也会被回收,导致你订阅的showTimerFlow彻底失去数据源,自然不会有任何事件发射。ConfigurationViewModel能正常工作的原因
另一个ViewModel里,你是通过**闭包(比如Flow的lambda表达式)**捕获了repository。闭包会隐式持有repository的强引用,而这个闭包又被ViewModel的Flow属性持有,相当于间接把repository的生命周期和ViewModel绑定了,所以repository不会被GC,它内部的Flow也能正常工作。
补充验证:你可以尝试在OverlaySensorViewModel里,即使去掉val,但在类里加一行private val _unused = repository,通过这个变量持有repository的强引用,showTimer的订阅就会恢复正常,这也能直接验证是GC导致的问题。
内容的提问来源于stack exchange,提问作者Selali Adobor

