繁体   English   中英

为什么使用 viewLifecycleOwner 观察到的 LiveData 在 onDestroyView 之后会得到回调?

[英]Why would a LiveData observed with viewLifecycleOwner get callbacks after onDestroyView?

我有一个使用视图绑定的 Fragment,因此它在onCreateView设置了它的_binding成员变量,并在onDestroyView _binding_binding空。 onViewCreated ,我使用viewLifecycleOwner作为 LifecycleOwner 从视图模型观察 LiveData。 (实际上,这分为片段和基类,但我看不出这将如何解释其中的任何一个)

我无法在内部重现这一点,但 crashlytics 正在报告现场情况,当绑定为 null 时,LiveData 的观察者被回调,这让我认为在调用onDestroyView之后会以某种方式调用它。 知道这怎么可能吗?

我有许多类似的片段,所以另一种解释是用户正在这些片段之间导航(使用 Jetpack Navigation),并且我们在再次设置绑定之前以某种方式调用了 LiveData 观察器,但我看不到如何在onCreateView之前调用onViewCreated ,即使在向后导航时也是如此。

abstract class MyFragmentBase : Fragment() {
    ...

    protected abstract val someView: View
 
    override fun onViewCreated(
        view: View, 
        savedInstanceState: Bundle?
    ) {
        super.onViewCreated(view, savedInstanceState)
        viewModel.someLiveData.observe(viewLifecycleOwner) { flag ->
            someView.isVisible = flag
       }
    }

    ...
}
class MyFragment : MyFragmentBase() {
    private var _binding: MyFragmentBinding? = null
    // This property is only valid between onCreateView and
    // onDestroyView.
    private val binding get() = _binding!!

    override val someView: View
        get() = binding.someView

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = MyFragmentBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }

    ...
}

不是observe(viewLifecycleOwner)意味着观察者与片段的生命周期有关吗?

是的,但这并不意味着观察者已经死了, LiveData本身在ViewModel维护,并且观察者对象仍然存在于片段的旧实例中

由于此LiveData跨越MyFragmentBase片段; 在片段之间切换应该最终将一个全新的观察者附加到LiveData ,但旧的观察者并没有从liveData分离。

因此,您可以尝试在使用removeObserver()销毁片段时分离/删除观察者:

abstract class MyFragmentBase : Fragment() {
    ...

    protected abstract val someView: View
    
    val observer = Observer<Boolean> { flag ->
        someView.isVisible = flag
    }   
 
    override fun onViewCreated(
        view: View, 
        savedInstanceState: Bundle?
    ) {
        super.onViewCreated(view, savedInstanceState)
        
        // Attach the observer
        viewModel.someLiveData.observe(viewLifecycleOwner, observer)       
       
    }


    override fun onDestroyView() {
        super.onDestroyView()
        // Detach the observer
        viewModel.someLivedata.removeObserver(observer)
    }

    ...
}

这也应该消除连接到销毁片段的实时观察者的任何内存泄漏

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM