以前写过一篇 Navigation 导致内存泄漏的文章 Android 解决XXX Layout leaked 使用Navigation 踩坑 XML内存泄漏
,这次算补充吧。
场景是 当一个有RecyclerView的页面跳转的时候发生内存泄漏的
还是先上报错图
最后是指向的adapter
先看错误代码
class HomeFragment : Fragment() {
private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!
private var taskAdapter: TaskAdapter? = null
private var tasks = mutableListOf<String>()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
return binding.root
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
loadTask()
observeData()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
initView()
}
private fun loadTask() {}
private fun observeData() {}
private fun initView() {
taskAdapter = TaskAdapter()
binding.homeTaskList.layoutManager = GridLayoutManager(requireContext(), 3)
binding.homeTaskList.adapter = taskAdapter?.apply {
isAnimationFirstOnly = false
setAnimationWithDefault(BaseQuickAdapter.AnimationType.ScaleIn)
setOnItemClickListener { _, _, position ->
findNavController().navigate(HomeFragmentDirections.actionHomeToCollect(position))
}
}
taskAdapter?.setList(tasks)
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
错误原因分析:
因为上一篇博文写的经历,我首先想到的是,页面跳转的时候,fragment 对象还在,但是View被回收,估计是有哪个View的引用被Fragment持有了,销毁不掉造成的,然后来看一下泄漏描述,最后
recyclerViewOrNull是我的Adapter 继承得来的
而recyclerViewOrNull 源码中是这样的
那就很直观了 这就是关联的哪个RecyclerView
和一开始猜的一样Adapter持有了RecyclerView,界面跳转,RecyclerView销毁,Adapter持有、销毁不了,然后内存泄漏,那就简单了
解决方法就是在onDestroyView 加一个置为null就可以了
override fun onDestroyView() {
super.onDestroyView()
taskAdapter = null
_binding = null
}