RecyclerView进行数据更新时焦点丢失的解决方案
在使用RecyclerView时,难免会用到adapter的notifyDataSetChanged方法来更新数据,其实notify**Changed系列方法都存在一个已知的焦点丢失的bug,如果在notify之后重新手动requestFocus,又会导致焦点可能不对应的问题。
可以使用如下步骤规避此问题:
1.为adapter提供stableId:
stableId在Listview和RecyclerView中都被用来定位一个item,官方建议使用item本身的hashcode或item内部的属性的hashcode,来唯一标识一个item,因此,需要在adapter中复写此方法:
@Override
public long getItemId(int position) {
return position;
}
更简单一点,可以如上代码所示直接return item的position。
2.设置item的setHasStableIds()为true:
adapter.setHasStableIds(true);
在listview中也有复写此方法的方案。
3.在官方推荐的做法来看,这两步已经可以保存recyclerview的焦点了,但是使用notify系列方法仍然会出现focus丢失的问题,现在官方已经承认这是一个bug,可以暂时使用禁用notifyDataSetChanged动画的方法来规避:
mRecyclerView.setItemAnimator(null);
这种写法禁用了所有的item动画,你也可以只禁用notifyDataSetChanged来实现同样的效果。
更多关于stableId的讨论请前往 http://stackoverflow.com/questions/10267731/android-how-to-make-an-adapter-with-stable-ids
更多关于禁用动画的方法请前往: http://stackoverflow.com/questions/29873859/how-to-implement-itemanimator-of-recyclerview-to-disable-the-animation-of-notify
关于第三步提到的bug请前往: https://code.google.com/p/android/issues/detail?id=204277