使用 jetpack 导航时,RecyclerView 会导致内存泄漏吗?

will RecyclerView cause a memory leak while working with jetpack navigation?

假设我有这样一个片段

class MyFragment : Fragment() {

    // Suppose there is a binding, which contains a recyclerView
    private var _binding: FragmentAbinding? = null
    val binding get() = _binding!!
    
    // Suppose there is a recyclerView adapter
    val adapter by lazy { MyAdapter() }

    // use navigation as router
    private val navController: NavController by lazy { findNavController() }

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

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

        // ...
        binding.recyclerView.adapter = adapter
        // ...
    }

    override fun onDestroyView() {
        _binding = null
    }
}

当使用navController.navigate(...)时,MyFragment会被替换,并且_binding 将为空。然而,由于recyclerView使用观察者模式观察适配器中的数据集,因此适配器将持有recyclerView作为其观察者。导航到另一个fragment后(即onDestroyView()后),recyclerView会不会主动取消对adapter数据集的观察,也就是说adapter不会持有recyclerView的实例?

我使用下面的方法删除适配器数据集观察者

fun RecyclerView.Adapter<*>.removeObservers() {
    var clazz: Class<*> = javaClass
    val simpleName = RecyclerView.Adapter::class.simpleName
    while (clazz.simpleName != simpleName) {
        clazz = clazz.superclass
    }
    val field = clazz.getDeclaredField("mObservable")
    field.isAccessible = true
    val observable = field[this] as Observable<*>
    observable.unregisterAll()
}

// in fragment
class MyFragment : Fragment() {

    override fun onDestroyView() {
        adapter.removeObservers()
    }
}

适配器在调用“onCreateViewHolder”时使用 recyclerView 作为视图组,当您使用导航进行导航时,您的片段只是视图被销毁但它的实例仍然存在于后台堆栈中,您的适配器也是如此,因为那是一个 class-level 解决这个问题的变量你应该在视图生命周期事件(onViewCreated.. onDestroyView)中创建适配器。