Android:如何移除ViewTreeObserver的GlobalLayoutListener?当前方法是否正确?
正确移除ViewTreeObserver监听器的方法
你当前的代码存在核心错误:你添加的是OnGlobalLayoutListener布局变化监听器,但移除时调用了针对OnGlobalFocusChangeListener焦点变化监听器的方法,两者完全不匹配,根本无法移除你之前添加的监听器。
正确步骤:
保存监听器实例引用
不能直接用匿名lambda添加监听器,因为移除时需要传入同一个实例才能生效,所以要把监听器存为Fragment的成员变量。调用对应类型的移除方法
监听器类型和移除方法是一一对应的:- 添加
OnGlobalLayoutListener→ 用removeOnGlobalLayoutListener移除 - 添加
OnGlobalFocusChangeListener→ 用removeOnGlobalFocusChangeListener移除 - 其他监听器类型同理,调用同名的remove方法
- 添加
选择合适的移除时机
对于Fragment,推荐在onDestroyView中移除监听器,因为此时视图即将被销毁,能更及时避免内存泄漏,比onDestroy更合适。
修改后的代码示例:
class MyFragment: Fragment() { // 保存布局变化监听器的实例引用 private val globalLayoutListener = ViewTreeObserver.OnGlobalLayoutListener { doSomething() } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding.root.viewTreeObserver.addOnGlobalLayoutListener(globalLayoutListener) } override fun onDestroyView() { super.onDestroyView() // 调用对应类型的移除方法,传入同一个监听器实例 binding.root.viewTreeObserver.removeOnGlobalLayoutListener(globalLayoutListener) } }
额外说明
如果你的minSdkVersion >= 16,也可以使用removeOnGlobalLayoutListener的重载方法,但保持监听器实例一致是最通用、不易出错的做法。
内容的提问来源于stack exchange,提问作者Lance Samaria
相关产品推荐
相关产品推荐

