Android Fragment使用setSupportActionBar设置独立Toolbar出现内存泄漏如何解决
问题根源
内存泄漏的核心原因是:调用setSupportActionBar后,宿主Activity会持久持有传入的Toolbar实例。如果该Toolbar属于Fragment的视图结构,Fragment销毁视图时Activity还没销毁,就会导致Fragment的视图资源无法被回收,产生内存泄漏。
可行解决方案
方案1:保留setSupportActionBar实现,补充生命周期清理逻辑
- 在Fragment的
onDestroyView回调中,主动调用宿主Activity的setSupportActionBar(null),清空Activity对Fragment侧Toolbar的持有引用即可解决泄漏问题
示例代码:
// onViewCreated 中原有设置Toolbar逻辑 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val toolbar = view.findViewById<Toolbar>(R.id.fragment_toolbar) (requireActivity() as AppCompatActivity).setSupportActionBar(toolbar) // 开启导航按钮显示 (requireActivity() as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled(true) } // 关键补充:销毁视图时清空ActionBar引用 override fun onDestroyView() { (requireActivity() as AppCompatActivity).setSupportActionBar(null) super.onDestroyView() } // 原有重写导航按钮事件逻辑不变 override fun onOptionsItemSelected(item: MenuItem): Boolean { if (item.itemId == android.R.id.home) { // 弹出操作确认弹窗逻辑 showExitConfirmDialog() return true } return super.onOptionsItemSelected(item) }
方案2:不绑定ActionBar,直接处理Toolbar导航点击(更推荐,无泄漏风险)
不需要将Toolbar交给Activity托管作为ActionBar,直接给Toolbar设置导航点击监听即可满足需求,从根源避免Activity持有Toolbar导致的泄漏:
示例代码:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val toolbar = view.findViewById<Toolbar>(R.id.fragment_toolbar) // 手动设置导航图标 toolbar.setNavigationIcon(R.drawable.ic_baseline_arrow_back_24) // 直接设置导航点击监听 toolbar.setNavigationOnClickListener { // 弹出操作确认弹窗逻辑 showExitConfirmDialog() } // 如果有菜单需求,直接给Toolbar填充菜单、设置菜单点击监听即可,不需要联动Activity的onCreateOptionsMenu toolbar.inflateMenu(R.menu.fragment_specific_menu) toolbar.setOnMenuItemClickListener { item -> // 处理菜单点击逻辑 true } }
内容的提问来源于stack exchange,提问作者Don Robin
相关产品推荐
相关产品推荐

