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

一直只知道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 局部刷新的坑

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现两个RecyclerView item之间的拖拽动画,可以使用ItemTouchHelper类。以下是基本步骤: 1. 创建一个实现ItemTouchHelper.Callback的类,重写以下方法: - onMove():当用户拖动item时,返回true,同时交换item的位置。 - onSwiped():当用户滑动item时,执行删除或其他操作。 - getMovementFlags():设置拖拽和滑动的方向。 2. 在RecyclerView的Adapter中实现ItemTouchHelperAdapter接口,重写以下方法: - onItemMove():当item被移动时,将item的位置交换。 - onItemDismiss():当item被删除时,执行删除操作。 3. 在Activity或Fragment中创建ItemTouchHelper实例,并将其附加到RecyclerView上。 4. 在Adapter中实现动画效果,可以使用ItemAnimator类。例如,使用DefaultItemAnimator类实现默认的动画效果。 以下是示例代码: ```kotlin class MyItemTouchHelperCallback(private val adapter: ItemTouchHelperAdapter) : ItemTouchHelper.Callback() { override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int { val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN val swipeFlags = ItemTouchHelper.START or ItemTouchHelper.END return makeMovementFlags(dragFlags, swipeFlags) } override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean { adapter.onItemMove(viewHolder.adapterPosition, target.adapterPosition) return true } override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { adapter.onItemDismiss(viewHolder.adapterPosition) } } interface ItemTouchHelperAdapter { fun onItemMove(fromPosition: Int, toPosition: Int) fun onItemDismiss(position: Int) } class MyAdapter(private val data: MutableList<String>) : RecyclerView.Adapter<MyAdapter.ViewHolder>(), ItemTouchHelperAdapter { // ... override fun onItemMove(fromPosition: Int, toPosition: Int) { // 交换item Collections.swap(data, fromPosition, toPosition) notifyItemMoved(fromPosition, toPosition) } override fun onItemDismiss(position: Int) { // 删除item data.removeAt(position) notifyItemRemoved(position) } // ... } // 在Activity或Fragment中 val callback = MyItemTouchHelperCallback(adapter) val touchHelper = ItemTouchHelper(callback) touchHelper.attachToRecyclerView(recyclerView) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值