如果在 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了。