一直只知道recycleview局部刷新就想到notifyItemchanged()方法,里面传入position即可,用起来的时候是方便,但有时候却不能满足现在的需求,于是就百度。
先看几个常用的刷新方法
notifyDataSetChanged(),
notifyItemChanged(int position)
这两个是再不能常见的。
notifyDataSetChanged()
看源码解释:
/*** Notify any registered observers that the data set has changed.** <p>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.</p>** <p>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.</p>** <p><code>RecyclerView</code> 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.</p>** <p>If you are writing an adapter it will always be more efficient to use the more* specific change events if you can. Rely on <code>notifyDataSetChanged()</code>* as a last resort.</p>** @see #notifyItemChanged(int)* @see #notifyItemInserted(int)* @see #notifyItemRemoved(int)* @see #notifyItemRangeChanged(int, int)* @see #notifyItemRangeInserted(int, int)* @see #notifyItemRangeRemoved(int, int)*/
有道翻译
/ * **通知任何已登记的观察员数据集已更改。*有两类不同的数据更改事件,项目更改和结构更改*更改。项更改是指单个项的数据已更新,但没有位置信息*发生了变化。结构更改是指插入、删除或移动项*在数据集中。** 这个事件没有指定数据集发生了什么变化,强制执行*任何观察员假设所有现有项目和结构可能不再有效。* 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 <code>position</code> has changed.
* Equivalent to calling <code>notifyItemChanged(position, null);</code>.
*
* <p>This is an item change event, not a structural change event. It indicates that any
* reflection of the data at <code>position</code> is out of date and should be updated.
* The item at <code>position</code> retains the same identity.</p>
*
* @param position Position of the item that has changed
*
* @see #notifyItemRangeChanged(int, int)
*/
有道:
/ * **通知任何已登记的观察员,在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 at <code>position</code> has changed with* an optional payload object.** <p>This is an item change event, not a structural change event. It indicates that any* reflection of the data at <code>position</code> is out of date and should be updated.* The item at <code>position</code> retains the same identity.* </p>** <p>* 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.* <p>* 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 <code>position</code> 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<Object> payloads) {onBindViewHolder(holder, 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.* <p>* 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 <code>position</code> 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.* <p>* Partial bind vs full bind:* <p>* 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 局部刷新的坑