Home > Mobile >  How to prevent scroll resetting when Adapter data is updated
How to prevent scroll resetting when Adapter data is updated

Time:01-23

I am creating chat app and I want to refresh my data every second but problem is that recyclerview scroll reset their first position.How to get rid of this.Thanks in Advance :)

I used MySql sserver to add andd fetch data.

CodePudding user response:

In the adapter constructor call setHasStableIds with true.

Secondly, override the getItemId method in the adapter, making sure it returns a message unique identifier from your dataset (ie: cursor).

Make sure that each message always has a unique identifier which doesn't change even when refreshed.

Next some examples. Logically you need to keep the same Adapter instance all the time for the RecyclerView, and update only its underlying dataset (cursor) whenever it changes. The updateData method could be further optimized to make use of DiffUtil, but that would be already a different question.

Example 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
}

Example 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
}

CodePudding user response:

Saving the current scroll position: (Usually called in activity onPause())

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

Restoring the scroll position after you have set adapter data: (Called whenever you set/refresh your adapter data)

recyclerView.getLayoutManager().scrollToPositionWithOffset(positionIndex, topView);
  •  Tags:  
  • Related