如何在RecyclerAdapter ViewHolder中实现LifecycleOwner并正确调用onDestroy
解决方案:LifecycleViewHolder的onDestroy()调用位置
你需要在两个位置调用该方法,覆盖所有销毁场景:
1. Adapter的onViewRecycled回调
这是ViewHolder被系统回收、不再用于展示数据时的标准回调,直接在你的自定义LifecyclePagingDataAdapter中重写该方法即可:
abstract class LifecyclePagingDataAdapter<T: Any, VH: LifecycleViewHolder>(diffCallback: DiffUtil.ItemCallback<T>) : PagingDataAdapter<T, VH>(diffCallback) { override fun onViewAttachedToWindow(holder: VH) { super.onViewAttachedToWindow(holder) holder.onAppear() } override fun onViewDetachedFromWindow(holder: VH) { super.onViewDetachedFromWindow(holder) holder.onDisappear() } // 新增如下代码 override fun onViewRecycled(holder: VH) { super.onViewRecycled(holder) holder.onDestroy() } }
2. 列表宿主(Activity/Fragment)销毁时主动调用
当列表所在的页面整体销毁时,当前还在屏幕上展示的ViewHolder不会触发onViewRecycled回调,需要主动遍历所有附着的ViewHolder调用销毁方法,避免内存泄漏:
首先在Adapter中新增工具方法:
fun destroyAllHolders(recyclerView: RecyclerView) { recyclerView.children.forEach { childView -> (recyclerView.getChildViewHolder(childView) as? VH)?.onDestroy() } }
然后在宿主的销毁生命周期中调用,例如Fragment的onDestroyView:
override fun onDestroyView() { super.onDestroyView() yourAdapter.destroyAllHolders(yourRecyclerView) }
补充适配:支持ViewHolder复用
官方LifecycleRegistry不允许从DESTROYED状态回退到活跃状态,如果你需要复用ViewHolder,需要调整LifecycleViewHolder的代码适配场景:
abstract class LifecycleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), LifecycleOwner { // 改为var,支持复用场景重置 private var lifecycleRegistry = LifecycleRegistry(this) init { resetLifecycleState() } private fun resetLifecycleState() { lifecycleRegistry = LifecycleRegistry(this) lifecycleRegistry.currentState = Lifecycle.State.INITIALIZED lifecycleRegistry.currentState = Lifecycle.State.CREATED } fun onAppear() { // 复用场景下先重置状态 if (lifecycleRegistry.currentState == Lifecycle.State.DESTROYED) { resetLifecycleState() } lifecycleRegistry.currentState = Lifecycle.State.STARTED lifecycleRegistry.currentState = Lifecycle.State.RESUMED } fun onDisappear() { lifecycleRegistry.currentState = Lifecycle.State.STARTED lifecycleRegistry.currentState = Lifecycle.State.CREATED } fun onDestroy(){ lifecycleRegistry.currentState = Lifecycle.State.DESTROYED } override fun getLifecycle(): Lifecycle { return lifecycleRegistry } }
完成上述修改后,你在ViewHolder中绑定的LiveData Observer会在DESTROYED触发时被自动移除,lifecycle.coroutineScope启动的协程也会被自动取消,不需要额外手动清理。
内容的提问来源于stack exchange,提问作者John Santos
相关产品推荐
相关产品推荐

