recycleView局部更新item notifyItemChanged()几个方法区别

一直只知道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 notifyDataSetChanged() * as a last resort.

* * @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 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.


         *
         * @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 position 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 at position 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 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.
 * 

* 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 局部刷新的坑

你可能感兴趣的:(个人经历,recycleview)