文章目录

  • 一、在RecyclerView的Item的onBindViewHolder时,利用一个CountDownTimer去做一个倒计时显示 / 或者是有一个属性动画效果?
  • 二、onAttachedToWindow和onDetachedFromWindow调用时机
  • 2.1、onAttachedToWindow中能否取得View的宽高
  • 三、相关文章


一、在RecyclerView的Item的onBindViewHolder时,利用一个CountDownTimer去做一个倒计时显示 / 或者是有一个属性动画效果?

到底在什么时候可以cancel掉这个倒计时/ 动画,而不影响功能了(滑动到用户可见范围内,倒计时/动画 运作正常)?
有什么方法可以和onBindViewHolder 对应吗?就像onAttachedToWindow ,onDetachedFromWindow这样 。

  • onAttachedToWindowonDetachedFromWindowRecyclerView中还适用吗?

RecyclerView中,Item的这两个方法分别会在【首次出现】和【完全滑出屏幕】(即在屏幕中完全不可见)时回调(在Adapter中也可以重写同名方法,用来监听ViewHolder的出现和消失)。

至于说适不适用,还是看具体需求,比如列表中的视频播放,在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被完全滑出屏幕时,AdapteronDetachedFromWindow和该ItemonDetachedFromWindow会被回调,也就是说,当onDetachedFromWindow被回调时,ViewHolder并没有真正被回收!如果这时候把倒计时/动画取消掉了,那么在它们再次出现在屏幕中的时候,就不会动了,因为是直接重用,不会重新绑定数据的。

  • 那应该在什么时候取消?

Adapter中有个onViewRecycled方法,看名字就知道是当Item被回收后回调的。。。

没错了,这个方法回调时,表示这个Holder已经被扔进mRecyclerPool.mScrap里了,也就是再次取出的时候会经过onBindViewHolder方法重新绑定数据。

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

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

有同学可能会说:我不见得非要在onViewRecycled方法中取消才能正常运作,我在onDetachedFromWindow中取消,在onAttachedToWindow恢复,不行吗?

可以是可以。。。但你这不是多做了事情了嘛,人家onBindViewHolder本来就已经承担了恢复的工作了。。。

二、onAttachedToWindow和onDetachedFromWindow调用时机

1、onAttachedToWindow调用顺序:ActivityThread.handleResumeActivity->WindowManagerImpl.addView->WindowManagerGlobal.addView->ViewRootImpl.performTraversals->ViewGroup.dispatchAttachedToWindow->View.dispatchAttachedToWindow->onAttachedToWindow

2、onDetachedFromWindow调用顺序:ActivityThread.handleDestroyActivity->WindowManagerImpl.removeViewImmediate->WindowManagerGlobal.removeView->ViewRootImpl.die->ViewRootImpl.doDie->ViewRootImpl.dispatchDetachedFromWindow->ViewGroup.dispatchDetachedFromWindow->View.dispatchDetachedFromWindow->onDetachedToWindow

3、onAttachedToWindowonDetachedFromWindow的调用与visibility无关。

4、onAttachedToWindow是先调用自己,然后调用儿子View的。onDetachedFromWindow是先调用儿子View的,然后再调用自己的。

2.1、onAttachedToWindow中能否取得View的宽高

onAttachedToWindow() 里并不能拿到View的宽高信息的,可以通过View.post来获取宽高信息。

三、相关文章

【1】每日一问:浅谈 onAttachedToWindow 和 onDetachedFromWindow 【2】onAttachedToWindow和onDetachedFromWindow调用时机源码解析