RecyclerView 回收机制和资源释放问题探究

如果在 View 中持有的资源,我们可以监听的 onAttachedToWindow ,onDetachedFromWindow 来进行控制。那么onAttachedToWindow和onDetachedFromWindow在RecyclerView中还适用吗?在RecyclerView中,Item的这两个方法分别会在【首次出现】和【完全滑出屏幕】(即在屏幕中完全不可见)时回调。

至于说适不适用,还是看具体需求,比如列表中的视频播放,在onDetachedFromWindow回调时暂停/停止还是合理的。但是像倒计时或者属性动画效果,就不合适了。

这里我们先说一下RecyclerView的回收机制:

RecyclerView在布局(自然滑动其实也是反复布局子View)时,会回收一些符合条件的ViewHolder,它会根据ViewHolder的状态来决定临时存放在哪个地方,且把这些临时存放ViewHolder的集合看作两种:

  • 不需要经过onBindViewHolder能直接重用的(mAttachedScrap、mCachedViews);
  • 需要经过onBindViewHolder重新绑定数据的(mRecyclerPool.mScrap);

mAttachedScrap,正常情况下,它会在RecyclerView每次布局时都用到:在布局子View时,会把全部子View所属的Holder,都临时放里面,计算好了每个子View的新位置后,会一个个从mAttachedScrap中取出来,当然了不一定是全部都会取出来的,因为可能本次布局,一些旧Item已经完全滑出屏幕了。

那么,这些留在mAttachedScrap中没有被取出来的ViewHolder会怎么样呢?

正常情况下,它们会被扔到mCachedViews里面去(注意从mCachedViews中取出来时也是不用重新绑定数据的,即不会经过onBindViewHolder方法)。

刚刚说过,当Item被完全滑出屏幕时,Adapter的onDetachedFromWindow和该Item的onDetachedFromWindow会被回调,也就是说,当onDetachedFromWindow被回调时,ViewHolder并没有真正被回收!如果这时候把倒计时/动画取消掉了,那么在它们再次出现在屏幕中的时候,就不会动了,因为是直接重用,不会重新绑定数据的。

那应该在什么时候取消?Adapter中有个onViewRecycled方法,看名字就知道是当Item被回收后回调的。没错了,这个方法回调时,表示这个Holder已经被扔进mRecyclerPool.mScrap里了,也就是再次取出的时候会经过onBindViewHolder方法重新绑定数据。

倒计时/动画在这里取消的话,是完全没问题的(但记得保存当前进度,以便下次恢复)。

所以与onBindViewHolder对应的方法,就是这个onViewRecycled了。

原文地址:https://www.cnblogs.com/renhui/p/12587179.html