一直只知道recycleview局部刷新就想到notifyItemchanged()方法,里面传入position即可,用起来的时候是方便,但有时候却不能满足现在的需求,于是就百度。
先看几个常用的刷新方法
notifyDataSetChanged(),
notifyItemChanged(int position)
这两个是再不能常见的。
notifyDataSetChanged()
看源码解释:
/** * Notify any registered observers that the data set has changed. * *There are two different classes of data change events, item changes and structural * changes. Item changes are when a single item has its data updated but no positional * changes have occurred. Structural changes are when items are inserted, removed or moved * within the data set.
* *This event does not specify what about the data set has changed, forcing * any observers to assume that all existing items and structure may no longer be valid. * LayoutManagers will be forced to fully rebind and relayout all visible views.
* ** *
RecyclerView
will attempt to synthesize visible structural change events * for adapters that report that they have {@link #hasStableIds() stable IDs} when * this method is used. This can help for the purposes of animation and visual * object persistence but individual item views will still need to be rebound * and relaid out.If you are writing an adapter it will always be more efficient to use the more * specific change events if you can. Rely on
* * @see #notifyItemChanged(int) * @see #notifyItemInserted(int) * @see #notifyItemRemoved(int) * @see #notifyItemRangeChanged(int, int) * @see #notifyItemRangeInserted(int, int) * @see #notifyItemRangeRemoved(int, int) */notifyDataSetChanged()
* as a last resort.
有道翻译
/ * **通知任何已登记的观察员数据集已更改。*有两类不同的数据更改事件,项目更改和结构更改*更改。项更改是指单个项的数据已更新,但没有位置信息*发生了变化。结构更改是指插入、删除或移动项*在数据集中。** 这个事件没有指定数据集发生了什么变化,强制执行*任何观察员假设所有现有项目和结构可能不再有效。* LayoutManagers将被迫完全重新绑定和转发所有可见视图。** clerview 将尝试综合可见的结构变化事件*对于报告具有{@link #hasStableIds() stable id}的适配器使用这种方法。这对于动画和视觉的目的是有帮助的*对象持久性,但个别项目视图仍然需要反弹** 如果您正在编写适配器,那么使用越多总是越有效*如果可以的话,具体的变更事件。依靠<代码> notifyDataSetChanged() < /代码>作为最后的手段。**
@see # notifyItemChanged (int)*
@see # notifyItemInserted (int)*
@see # notifyItemRemoved (int)*
@参见#notifyItemRangeChanged(int, int)*
@参见# notifyitemrangeinsert (int, int)*
@参见#notifyItemRangeRemoved(int, int)* /
这个是里面的一个方法,回遍历集合,每个改变,我的理解就是会把这个集合下的数据都刷新一下包括控件
public void notifyChanged() { // since onChanged() is implemented by the app, it could do anything, including // removing itself from {@link mObservers} - and that could cause problems if // an iterator is used on the ArrayList {@link mObservers}. // to avoid such problems, just march thru the list in the reverse order. for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onChanged(); } }
所以对于这个方法就把所以的控件和数据更新
notifyItemChanged(int position)方法
/**
* Notify any registered observers that the item at position
has changed.
* Equivalent to calling notifyItemChanged(position, null);
.
*
*
This is an item change event, not a structural change event. It indicates that any
* reflection of the data at position
is out of date and should be updated.
* The item at position
retains the same identity.
有道:
/ * **通知任何已登记的观察员,在position处的项目已更改。*相当于调用notifyItemChanged(position, null);。*这是一个项目更改事件,而不是一个结构更改事件。它表明*数据在position处的反射已经过期,需要更新。*位于position的项保留相同的标识。** @param位置已更改项的位置**
@参见#notifyItemRangeChanged(int, int)* /
position是个标识,更改已经修改的地方,内部调用notifyItemRangeChanged(int, int),从命名就可以看到positionStart从这个位置开始,itemCount这里传入的是1,没有看源码不知道里面是什么情况,有点尴尬,
public void notifyItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) { // since onItemRangeChanged() is implemented by the app, it could do anything, including // removing itself from {@link mObservers} - and that could cause problems if // an iterator is used on the ArrayList {@link mObservers}. // to avoid such problems, just march thru the list in the reverse order. for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onItemRangeChanged(positionStart, itemCount, payload); } }
这里也是循环对象,不过增加了位置从哪里开始。
上面的两个方法粗略地解释了一下,那么说说另一个方法;
notifyItemChanged(int position, @Nullable Object payload)
是不是很陌生,对于我来说是这样的,以前一般都
notifyDataSetChanged()就ok了
还是先看看官方解释:
/** * Notify any registered observers that the item atposition
has changed with * an optional payload object. * *This is an item change event, not a structural change event. It indicates that any * reflection of the data at
* *position
is out of date and should be updated. * The item atposition
retains the same identity. ** Client can optionally pass a payload for partial change. These payloads will be merged * and may be passed to adapter's {@link #onBindViewHolder(ViewHolder, int, List)} if the * item is already represented by a ViewHolder and it will be rebound to the same * ViewHolder. A notifyItemRangeChanged() with null payload will clear all existing * payloads on that item and prevent future payload until * {@link #onBindViewHolder(ViewHolder, int, List)} is called. Adapter should not assume * that the payload will always be passed to onBindViewHolder(), e.g. when the view is not * attached, the payload will be simply dropped. * * @param position Position of the item that has changed * @param payload Optional parameter, use null to identify a "full" update * * @see #notifyItemRangeChanged(int, int) */
有道:
/ * **通知任何已登记的观察员,在position处的项目已更改*一个可选的有效负载对象。*这是一个项目更改事件,而不是一个结构更改事件。它表明*数据在position处的反射已经过期,需要更新。*位于position的项目保持相同的标识。* < / p >** < p >*客户端可以选择性地为部分更改传递有效负载。这些有效载荷将被合并和可能被传递到适配器的{@link #onBindViewHolder(ViewHolder, int, List)}*项目已经由ViewHolder表示,它将被反弹到相同的值* ViewHolder。带有null有效负载的notifyItemRangeChanged()将清除所有现有的数据*有效载荷,并防止未来的有效载荷,直到调用* {@link #onBindViewHolder(ViewHolder, int, List)}。适配器不应假定*有效负载将始终传递给onBindViewHolder(),例如当视图不存在时*附加,有效载荷将被简单地丢弃。**
@param位置已更改项的位置*
@param有效负载可选参数,使用null标识“完整”更新**
@参见#notifyItemRangeChanged(int, int)* /
如果看解释的话,一般还不能够理解;payload是一个object对象,可以传入任何,当调用这个方法时候,回调onBindViewHolder(ViewHolder, int, List),上面已经解释了,payload会被添加到集合中,再onBindViewHolder(ViewHolder, int, List)这个方法中体现出来,这时有点奇怪,这个方法一晃眼没觉得什么但是细心会发现和经常写的有点不一样,
onBindViewHolder(holder, position);是不是少了一个参数,没有list
看看
onBindViewHolder(@NonNull VH holder, int position)官方解释
/** * Called by RecyclerView to display the data at the specified position. This method should * update the contents of the {@link ViewHolder#itemView} to reflect the item at the given * position. ** Note that unlike {@link android.widget.ListView}, RecyclerView will not call this method * again if the position of the item changes in the data set unless the item itself is * invalidated or the new position cannot be determined. For this reason, you should only * use the
position
parameter while acquiring the related data item inside * this method and should not keep a copy of it. If you need the position of an item later * on (e.g. in a click listener), use {@link ViewHolder#getAdapterPosition()} which will * have the updated adapter position. * * Override {@link #onBindViewHolder(ViewHolder, int, List)} instead if Adapter can * handle efficient partial bind. * * @param holder The ViewHolder which should be updated to represent the contents of the * item at the given position in the data set. * @param position The position of the item within the adapter's data set. */
有道:
/ * ** clerview调用,显示指定位置的数据。这种方法应该*更新{@link ViewHolder#itemView}的内容,以反映给定的项*位置。* < p >*注意不像{@link android.widget。ListView},将不会调用此方法*同样,如果项目的位置在数据集中发生变化,除非项目本身发生变化*无效或无法确定新职位。出于这个原因,你只应该*在获取内部相关数据项时,使用position参数*此方法不应保留副本。如果您稍后需要项目的位置* on(例如,在单击侦听器中),使用{@link ViewHolder#getAdapterPosition()}*更新适配器位置。*如果适配器可以,则覆盖{
@link #onBindViewHolder(ViewHolder, int, List)}处理有效的部分绑定。**
@param持有ViewHolder,它应该被更新为表示*项目位于数据集中给定位置。*
@param定位适配器数据集中项的位置。* /
onBindViewHolder(@NonNull VH holder, int position, @NonNull List
/** * Called by RecyclerView to display the data at the specified position. This method * should update the contents of the {@link ViewHolder#itemView} to reflect the item at * the given position. ** Note that unlike {@link android.widget.ListView}, RecyclerView will not call this method * again if the position of the item changes in the data set unless the item itself is * invalidated or the new position cannot be determined. For this reason, you should only * use the
position
parameter while acquiring the related data item inside * this method and should not keep a copy of it. If you need the position of an item later * on (e.g. in a click listener), use {@link ViewHolder#getAdapterPosition()} which will * have the updated adapter position. ** Partial bind vs full bind: *
* 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 holder The ViewHolder which should be updated to represent the contents of the * item at the given position in the data set. * @param position The position of the item within the adapter's data set. * @param payloads A non-null list of merged payloads. Can be empty list if requires full * update. */
有道:
/ * ** clerview调用,显示指定位置的数据。这个方法*应该更新{@link ViewHolder#itemView}的内容,以反映项目at*给定的职位。* < p >*注意不像{@link android.widget。ListView},将不会调用此方法*同样,如果项目的位置在数据集中发生变化,除非项目本身发生变化*无效或无法确定新职位。出于这个原因,你只应该*在获取内部相关数据项时,使用position参数*此方法不应保留副本。如果您稍后需要项目的位置* on(例如,在单击侦听器中),使用{@link ViewHolder#getAdapterPosition()}*更新适配器位置。* < p >*局部绑定vs .完全绑定:* < p >*有效载荷参数是来自{@link #notifyItemChanged(int, Object)} or的合并列表* {@link #notifyItemRangeChanged(int, int, Object)}。如果有效载荷列表不是空的,* ViewHolder当前绑定到旧数据,适配器可能运行一个有效的部分*使用有效载荷信息进行更新。如果负载为空,适配器必须运行完整绑定。*适配器不应该假设传入notify方法的有效负载将被* onBindViewHolder ()。例如,当视图未附加到屏幕时notifyItemChange()中的有效负载将被简单地删除。** @param持有ViewHolder,它应该被更新为表示*项目位于数据集中给定位置。*
@param定位适配器数据集中项的位置。*
@param有效载荷合并有效载荷的非空列表。如果需要满列表,可以是空列表吗*更新。* /
这个viewholder和旧数据绑定一样,经过测试发现,这个方法会优先两个参数方法调用,如果这个方法存在,没有调用两个参数方法,那么两个参数的onBindViewHolder ()不会被调用。
至于用法这里没有写,可以给个链接
RecyclerView<第二篇>:刷新机制
RecyclerView 局部刷新的坑