【问题标题】:How to prevent scroll resetting when Adapter data is updated更新适配器数据时如何防止滚动重置
【发布时间】:2022-01-22 15:01:18
【问题描述】:

我正在创建聊天应用程序,我想每秒刷新一次数据,但问题是 recyclerview 滚动重置了他们的第一个位置。如何摆脱这个。提前致谢 :)

我使用 MySql sserver 来添加和获取数据。

【问题讨论】:

  • 请编辑问题并添加您尝试过的内容
  • 你用的是什么数据库?
  • 我正在使用 mySql
  • 你为什么不使用firebase?
  • 这是我的拼贴erp软件。为了和erp的网站合作,所以我用mySql而不是firebas

标签: java android android-recyclerview


【解决方案1】:

在适配器构造函数中使用 true 调用 setHasStableIds

其次,覆盖适配器中的getItemId 方法,确保它从您的数据集中返回消息唯一标识符(即:光标)。

确保每条消息始终有一个唯一标识符,即使刷新也不会改变。

接下来是一些例子。从逻辑上讲,您需要始终为 RecyclerView 保留相同的 Adapter 实例,并在其更改时仅更新其底层数据集(游标)。 updateData 方法可以进一步优化以使用DiffUtil,但这已经是另一个问题了。

Kotlin 示例:

class YourMessagesAdapter(private var messages: Cursor)
    : RecyclerView.Adapter<YourMessageItemViewHolder>() {

    init {
        setHasStableIds(true)

        // ... rest of your initialization as usual
    }

    override fun getItemId(position: Int): Long {
        return if (messages.moveToPosition(position)) {
            messages.getLong(YOUR_MESSAGE_COLUMN_ID_INDEX)
        } else RecyclerView.NO_ID
    }

    public fun updateData(newMessages: Cursor) {
        messages = newMessages
        notifyDataSetChanged()
    }

    // .... rest of your code as usual
}

Java 示例:

public final class YourMessagesAdapter
    extends RecyclerView.Adapter<YourMessageItemViewHolder> {

    @NonNull
    private Cursor messages;

    public YourMessagesAdapter(@NonNull final Cursor initialMessages) {

        setHasStableIds(true);
        messages = initialMessages;

        // ... rest of your initialization as usual
    }

    @Override
    public long getItemId(final int position) {
        if (messages.moveToPosition(position))
            return messages.getLong(YOUR_MESSAGE_COLUMN_ID_INDEX);

        return RecyclerView.NO_ID;  
    }

    public void updateData(@NonNull final Cursor newMessages) {
        messages = newMessages;
        notifyDataSetChanged();
    }
    
    // .... rest of your code as usual
}

【讨论】:

  • 你能举个例子吗?因为我听不懂你的回答
  • @erdharmik 在 Kotlin 和 Java 中添加了一个示例
【解决方案2】:

保存当前滚动位置:(通常在activityonPause()中调用)

int positionIndex = recyclerView.getLayoutManager().findFirstVisibleItemPosition();
View startView = recyclerView.getChildAt(0);
int topView = (startView == null) ? 0 : (startView.getTop() - rv.getPaddingTop());

设置适配器数据后恢复滚动位置:(在设置/刷新适配器数据时调用)

recyclerView.getLayoutManager().scrollToPositionWithOffset(positionIndex, topView);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多