Home » Android » android – RecyclerView scrolls to top after adding items-Exceptionshub

android – RecyclerView scrolls to top after adding items-Exceptionshub

Posted by: admin February 26, 2020 Leave a comment

Questions:

I have a RecyclerView that I use to display items in an activity. When I scroll to the bottom, I make another API call to fetch an additional set of data. When the items load, my RecyclerView scrolls to the top. I have tried the other solutions listed without success. I have attempted many if not all of the suggestions mentioned in similar threads. None of them worked for me.

activity_see_more.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/see_more_frameLayout" />
</LinearLayout>

In the SeeMoreActivity.java I override the following method from the MvpView

@Override
public void loadPropertiesForCategory(List<Property> propertyList) {
    Preferences sharedPref = new Preferences(this);
    if (!properties.containsAll(propertyList)) {
        properties.addAll(propertyList);
    }
    sharedPref.setFilterList(properties);
    ResultListFragment fragment = ResultListFragment.setTag("see_more_filter");
    getSupportFragmentManager().beginTransaction().add(R.id.see_more_frameLayout, fragment, "search").commit();
}

ResultListFragment.java

private void setListOfCategoryProperties() {
    page = 2;
    mSearchList = mPreferences.getFilterList();
    setListAdapter(false, false, View.VISIBLE, View.GONE, false);
    mResultRecycleView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
            if (linearLayoutManager != null && linearLayoutManager.findLastVisibleItemPosition() == mSearchList.size() - 1) {
                ((SeeMoreActivity) getActivity()).setLoadPropertiesParamsAndCallApi(page);
                if (mSearchList.size() != mPreferences.getFilterList().size()) {
                    page++;
                    mSearchList = mPreferences.getFilterList();
                    //mAdapter.notifyDataSetChanged();
                    mAdapter.notifyItemInserted(mSearchList.size() - 1);
                }
            }
        }
    });
}

public void listAdapter() {
    mResultRecycleView.setLayoutManager(new LinearLayoutManager(getContext()));
    mResultRecycleView.setItemAnimator(new DefaultItemAnimator());
    mResultRecycleView.setNestedScrollingEnabled(true);
    mResultRecycleView.setAdapter(mAdapter);
}

private void setListAdapter(boolean showDeleteButton, boolean changeVisibility, int showNoResult, int showNoSavedSearch, boolean reverseFavorite) {
        if (mSearchList != null && mSearchList.size() != 0) {
            if (changeVisibility) {
                setVisibility(View.VISIBLE, View.GONE, View.GONE);
            }
            mAdapter = new SearchListAdapter(R.layout.item_single_element, mSearchList, showDeleteButton, this, reverseFavorite);
            listAdapter();
        } else {
            setVisibility(View.GONE, showNoSavedSearch, showNoResult);
        }
    }

public void handleTags() {
        switch (mTag) {
            case "result_search":
                setListAdapterForHomeSearch();
                break;
            case "see_more_filter":
                setListOfCategoryProperties();
                break;
            case Constants.USER_FAVORITES_KEY:
                setListOfUserFavoriteProperties();
                break;
        }
    }
How to&Answers:

It’s a bit hard to tell, but it looks like you’re re-setting the adapter to a new adapter every time you receive more data. That resets a bunch of internal state in RecyclerView, so that’s probably what’s causing this.

To solve it, you should leave the existing adapter in place and instead call one of the Adapter.notify... methods (probably notifyItemRangeInserted) to inform the adapter that more data has been added. You could also use ListAdapter and its submitList method to automatically handle it for you.

Answer:

Issue was that I was creating a new instance of my fragment every time I made an API call. Now that I create only one instance and update the list by just adding new elements to it, everything works correctly.