前提:
上下滑视频列表,实现方式:RecyclerView+LinearLayoutManager
产品需求:
1.黑名单功能。videoList添加author进黑名单,删除该作者在本地列表的所有视频。
胖子的思路
1.从列表最后往前删除,防止remove时,由于索引产生变化的bug。
int tempVideoId = 0;
for (int i = mAdapter.getData().size() - 1; i >= 0; i--) {
BaseVideoBean baseVideoBean = mAdapter.getData().get(i);
if (null == baseVideoBean)
continue;
if (baseVideoBean.getAuthorInfo().getId() == userId) {
if (videoId == baseVideoBean.getId() && i + 1 <= mAdapter.getData().size() - 1) {//当删除到这一项时,判断是否有下一项,如果有,赋值
tempVideoId = mAdapter.getData().get(i + 1).getId();//这里代表删除项往后推,第一个未观看过的视频
}
mAdapter.removeAt(i);
}
}
2.根据tempVideoId的值,做相应的操作。
2.1 tempVideoId为0,直接play(size() - 1)
2.2 tempVideoId不为0,找到剩余列表里,与之匹配的video,然后play(对应的索引)
然后问题来了
因为视频上下切换的时候,胖子为了追求性能,这里是先release播放器,然后再添加。
好了,在胖子remove完后,立刻去播放相关视频,然后毛都没有。
最开始的找bug思路:
1.debug,看看index是否正确。
2.debug play()方法,看看相关逻辑,是否有return。
好了,毫无问题。
接着,debug RecyclerView.addOnChildAttachStateChangeListener,发现在胖子移除item时,不是立马调用onChildViewDetachedFromWindow,而是在play之后去调用。
mBinding.videoListRecycler.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {
@Override
public void onChildViewAttachedToWindow(@NonNull View view) {
}
@Override
public void onChildViewDetachedFromWindow(@NonNull View view) {
//这里,胖子release播放器
}
});
到这里,胖子突然想起了,RecyclerView的notifyItemRemoved是带动画效果的,既然带动画效果,那必然就会有duration,去看源码
private long mAddDuration = 120;
private long mRemoveDuration = 120;
private long mMoveDuration = 250;
private long mChangeDuration = 250;
private void animateRemoveImpl(final RecyclerView.ViewHolder holder) {
final View view = holder.itemView;
final ViewPropertyAnimator animation = view.animate();
mRemoveAnimations.add(holder);
animation.setDuration(getRemoveDuration()).alpha(0).setListener(
new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animator) {
dispatchRemoveStarting(holder);
}
@Override
public void onAnimationEnd(Animator animator) {
animation.setListener(null);
view.setAlpha(1);
dispatchRemoveFinished(holder);
mRemoveAnimations.remove(holder);
dispatchFinishedWhenDone();
}
}).start();
}
既然找到了原因,解决方法就油然而生了