在平时使用RecyclerView时,当想进行布局刷新时,我们通常会调用notifyItemChanged(int positon)进行布局刷新,如果item中图片的话,那么刷新就会出现闪烁,这是怎么回事了? 原因就是notifyItemChanged(int positon)是刷新整个item视图的,也就是重新调用onBindViewHolder方法进行item中所有控件的刷新,这自然会造成图片的重新设置了。
那么如果想要精细到刷新某个item中的某个控件呢?下面我就介绍下recyclerView中真正的布局刷新。
首先需要了解Adapter中的两个方法,一个是三个参数的onBindViewHolder(RecyclerView.ViewHolder holder, int position,List payloads),一个是两个参数的notifyItemChanged(int position, Object payload)。
看起来这2个方法比平时使用的多了一个payload参数,那么这个payload究竟有什么意义呢?在我的理解下,我认为payload可以用来存储一些变量值或者常数,然后在notifyItemChanged中传进去payload,指定某个item进行刷新,在这个Item的onBindViewHolder中就可以从第三个参数拿到传过来的payload。下面看看官方的解释。
* The payloads parameter is a merge list from {@link #notifyItemChanged(int, Object)} or
* {@link #notifyItemRangeChanged(int, int, Object)}. If the payloads list is not empty,
* the ViewHolder is currently bound to old data and Adapter may run an efficient partial
* update using the payload info. If the payload is empty, Adapter must run a full bind.
* Adapter should not assume that the payload passed in notify methods will be received by
* onBindViewHolder(). For example when the view is not attached to the screen, the
* payload in notifyItemChange() will be simply dropped.
* @param payloads A non-null list of merged payloads. Can be empty list if requires full
* update.
也就是说payloads是一个从notifyItemChanged(int, Object)中第二个参数和#notifyItemRangeChanged(int, int, Object)中第三个参数传进来的一个参数。如果payloads不为空并且viewHolder已经绑定了旧数据了,那么adapter会使用payloads参数进行布局刷新。如果payloads为空,adapter就会重新绑定数据,也就是刷新整个item。但是adapter不能保证payload通过nofityItemChanged方法会被onBindViewHolder接收,例如当view没有绑定到screen时,payloads就会失效被丢弃。
{#notifyItemChanged(int, Object)} or { #notifyItemRangeChanged(int, int, Object)}
public final void notifyItemChanged(int position, Object payload) {
mObservable.notifyItemRangeChanged(position, 1, payload);
public final void notifyItemRangeChanged(int positionStart, int itemCount, Object payload) {
mObservable.notifyItemRangeChanged(positionStart, itemCount, payload);
当我们调用只有一个参数的notifyItemChanged(int position)时 默认payload为null 也即会进行整个itemd的全部刷新,所以会造成图片闪烁的原因就是在这里。
public final void notifyItemChanged(int position) {
mObservable.notifyItemRangeChanged(position, 1);
mObservable中的notifyItemRangeChanged方法
public void notifyItemRangeChanged(int positionStart, int itemCount) {
notifyItemRangeChanged(positionStart, itemCount, null);
使用方法:
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position,List payloads) {
final ContactHolder contact= (ContactHolder) holder;
if(payloads.isEmpty()){
contact.userName.setText(mList.get(position).getName());
contact.userId.setText(mList.get(position).getId());
contact.userImg.setImageResources(mList.get(position).getImg());
}else{
int type= (int) payloads.get(0);
switch(type){
case 0:
contact.userName.setText(mList.get(position).getName());
break;
case 1:
contact.userId.setText(mList.get(position).getId());
break;
case 2:
contact.userImg.setImageResources(mList.get(position).getImg());
break;
public class ContactHolder extends RecyclerView.ViewHolder{
public CheckBox checkBox;
public TextView userName;
public TextView userId;
public ImageView userImg;
public ContactHolder(View itemView) {
super(itemView);
checkBox= (CheckBox) itemView.findViewById(R.id.ContactSelect_list_item_checkBox);
userName= (TextView) itemView.findViewById(R.id.ContactSelect_list_item_user_name);
userId= (TextView) itemView.findViewById(R.id.ContactSelect_list_item_user_employeeId);
userImg= (ImageView) itemView.findViewById(R.id.ContactSelect_list_item_img);
调用adapter.notifyItemChanged(position,payloads)或者直接在adapter中直接调用notifyItemChanged(position,payloads)进行刷新
mList.get(100).setName("Jason")
notifyItemChanged(100,0)
mList.get(102).setName("Yukito")
notifyItemChanged(102,0)
mList.get(10).setId("12306")
notifyItemChanged(10,1)
mList.get(100).setId("Jason")
mList.get(11).setId("110")
notifyItemChanged(11,0)
mList.get(20).setImg(R.drawable.img_one)
notifyItemChanged(20,0)
mList.get(26).setImg(R.drawable.img_two)
notifyItemChanged(26,0)
RecyclerView中实现checkBox单选布局刷新 实战:
http://blog.csdn.net/qq402164452/article/details/53462037
传入“null”就是更新全部!那我们调用的时候是传入什么呢!看下:
public final void notifyItemChanged(int position) {
mObservable.notifyItemRangeChanged(position, 1);
继而调用:
public void notifyItemRangeChanged(int positionStart, int itemCount) {
notifyI
局部刷新的方便之处
RecyclerView的刷新可以分为列表重新加载刷新、item刷新、item中局部刷新。对于前两种的刷新,都会是的列表刷新的时候闪烁一下,而后者则看不出列表有任何闪烁,并且,局部刷新能在一定程度上减少不必要的UI绘制渲染。
RecyclerView 数据刷新的几种方式,RecyclerView 真正的布局刷新的正确方式
notifyDataSetChanged() 刷新...
RecyclerView的刷新可以分为列表重新加载刷新、item刷新、item中局部刷新。对于前两种的刷新,都会是的列表刷新的时候闪烁一下,而后者则看不出列表有任何闪烁,并且,局部刷新能在一定程度上减少不必要的UI绘制渲染
RecyclerView 数据刷新的几种方式,RecyclerView 真正的布局刷新的正确方式
notifyDataSetChanged()刷新全部可见的item
notifyItemChanged(int position)更新列表position位置上的数据可以调用
这篇文章其实之前就完成了,一直遗忘在角落里了,今天无意翻之前的笔记发现的,大部分内容应该还是有效的。
之前在使用RecyclerView的遇到过一个问题,使用notifyItemChanged刷新数据的时候会出现重影或者闪烁的现象。
这个问题很容易出现,当我们的列表中有进度显示(比如下载),这时候需要不停的更新进度,就需要使用notifyItemChanged
使用notifyItemChanged可以只刷新那一个item,这样就避免了像ListView那样全部刷新
但是如果使用notifyItemC
在 Android 中,可以使用 RecyclerView.Adapter 中的 notifyDataSetChanged() 方法来通知 RecyclerView 刷新整个布局。这个方法会重新加载 RecyclerView 中的所有数据并刷新视图。
示例代码如下:
```java
adapter.notifyDataSetChanged();
当调用此方法时,RecyclerView 会重新加载所有数据并刷新视图。如果您只想刷新单个项目,则可以使用 RecyclerView.Adapter 中的 notifyItemChanged() 方法。
```java
adapter.notifyItemChanged(position);
其中,position 是要刷新的项目的位置。这个方法只会刷新指定位置的项目,而不会重新加载整个布局。
注意:使用 notifyDataSetChanged() 方法会刷新整个 RecyclerView,包括它的所有项和子项。在数据集较大时,这可能会导致性能问题。如果只需要更新特定项,则推荐使用 notifyItemChanged()。