初学Android,首次在项目中运用发生了RecyclerView刷新发生混乱的问题,困扰好久,终于解决,分享如下。
【问题现象】
项目中用RecyclerView做了一个医生排班列表,用于显示所有医生的排班信息,RecyclerView的一个项目(即一个医生),可以通过点前一周,下一周按钮查看不同周次的该医生的排班情况,编码很顺利,网上很多RecyclerView的例子,但在测试时发现,当第一次点击其中一个医生的下一周按钮时,结果该医生的数据却没有刷新,前一个医生的数据却被刷新了。
【调查过程】
通过debug发现了以下有趣的事情,在onBindViewHolder方法中,下一周按钮被点击时,被点击按钮所在项目(即holder对象)的ID假设为A,位置(即position)假设为7,在按钮事件被触发,通过Adapter.notifyDataSetChanged();触发RecyclerView刷新后,onBindViewHolder方法执行的时候,发现ID为A的holder的position发生了变更,不再是7了,而变成了6。holder的顺序发生了变更,但是adapter所绑定的数据的顺序却很正常,没发生变更,而这导致了上述现象的发生。
到底是什么原因导致position发生了变更呢?会不会是大牛的google开发人员的bug呢?如果是的话,android的开发者成千上万,早就发现这个问题并被反映解决了,又怎么能轮得到咱中大奖呢?所以说问题的原因很有可能是自己使用不当。但毕竟是android菜鸟,怎么解决毫无头绪,还是debug进源码看看到底为什么position会发生变更吧。我发现holder对象是在RecyclerView的getViewForPosition(int position)方法中被生成的。再往下细看,发现有一行给holder赋值的判断条件if (mAdapter.hasStableIds())没能走进去。我感觉很蹊跷,看看StableIds是个什么东西,有什么作用吧。hasStableIds()方法的注释如下:
/** * Returns true if this adapter publishes a unique <code>long</code> value that can * act as a key for the item at a given position in the data set. If that item is relocated * in the data set, the ID returned for that item should be the same. * * @return true if this adapter's items have stable IDs */写得很明确,感觉自己的问题就是它导致的。问题定位到这里,很容易查到了许多类似的问题和解决方法。如下:
【解决方法】
首先,在绑定adapter给RecycleView之前,设定adapter的stableIds为true。
adapter.setHasStableIds(true);
recyclerView.setAdapter(adapter);
其次,在adapter中,需要重写getItemId方法。
@Overridepublic long getItemId(int position) { return position;}
之后重新运行app,发现问题完美解决了。
更多RecyclerView的问题,可参阅如下文章。
http://blog.csdn.net/limonzet/article/details/56665727
联系客服