RecyclerView does not Recycling Views when use it inside NestedScrollView

AndroidAndroid RecyclerviewNestedscrollviewRecycle

Android Problem Overview


I'm using RecyclerView inside NestedScrollView. Also i set setNestedScrollingEnabled to false for recyclerview

to support lower API

ViewCompat.setNestedScrollingEnabled(mRecyclerView, false);

Now! When user scrolled the view every thing seems okay, but!!! views in recyclerview does not recycled!!! and Heap size grows swiftly!!

Update: RecyclerView layout manager is StaggeredLayoutManager

fragment_profile.xml:

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/coordinator"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

        <android.support.design.widget.AppBarLayout
            android:id="@+id/appbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" >
        </android.support.design.widget.AppBarLayout>

        <android.support.v4.widget.SwipeRefreshLayout
            android:id="@+id/profileSwipeRefreshLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >

                <!-- RecyclerView and NestedScrollView -->
                <include layout="@layout/fragment_profile_details" />

        </android.support.v4.widget.SwipeRefreshLayout>

</android.support.design.widget.CoordinatorLayout>

fragment_profile_details.xml:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/rootLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    android:orientation="vertical" >

        <android.support.v4.widget.NestedScrollView
            android:id="@+id/nested_scrollbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="fill_vertical"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            android:fillViewport="true"
            android:scrollbars="none" >

                <LinearLayout
                    android:id="@+id/nested_scrollbar_linear"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:descendantFocusability="blocksDescendants"
                    android:orientation="vertical" >

                        <android.support.v7.widget.CardView
                            android:id="@+id/profileCardview"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            app:cardBackgroundColor="@color/card_backgroind"
                            app:cardCornerRadius="0dp"
                            app:cardElevation="0dp" >

                            <!-- Profile related stuff like avatar and etc. --->

                        </android.support.v7.widget.CardView>

                        <android.support.v7.widget.RecyclerView
                            android:id="@+id/list_view"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:layout_marginBottom="@dimen/four"
                            android:layout_marginEnd="@dimen/four"
                            android:layout_marginLeft="@dimen/four"
                            android:layout_marginRight="@dimen/four"
                            android:layout_marginStart="@dimen/four"
                            android:layout_marginTop="@dimen/four"
                            app:layout_behavior="@string/appbar_scrolling_view_behavior"
                            android:clipToPadding="false" />

                </LinearLayout>
        </android.support.v4.widget.NestedScrollView>
</LinearLayout>

ProfileFragment.java:

mAdapter		= new MainAdapter(getActivity(), glide, Data);

listView		= (RecyclerView) view.findViewById(R.id.list_view);

ViewCompat.setNestedScrollingEnabled(listView, false);	
listView.setAdapter(mAdapter);

mStaggeredLM	= new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
mStaggeredLM.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);

listView.setLayoutManager(mStaggeredLM);
	
mScroll.setOnScrollChangeListener(new OnScrollChangeListener() {
		
		@Override
		public void onScrollChange(NestedScrollView arg0, int arg1, int arg2, int arg3, int arg4) {
            
			View view	= (View) mScroll.getChildAt(mScroll.getChildCount() - 1);
			int diff	= (view.getBottom() - ( mScroll.getHeight() + mScroll.getScrollY()));
			
			if(diff == 0){
				
				int visibleItemCount			= mStaggeredLM.getChildCount();
				int totalItemCount				= mStaggeredLM.getItemCount();
				
				int[] lastVisibleItemPositions	= mStaggeredLM.findLastVisibleItemPositions(null);
				int lastVisibleItemPos	= getLastVisibleItem(lastVisibleItemPositions);

				Log.e("getChildCount", String.valueOf(visibleItemCount));
                Log.e("getItemCount", String.valueOf(totalItemCount));
                Log.e("lastVisibleItemPos", String.valueOf(lastVisibleItemPos));
                
                if ((visibleItemCount + 5) >= totalItemCount) {
                
                	mLoadMore.setVisibility(View.VISIBLE);
                    Log.e("LOG", "Last Item Reached!");
                }
                
				mMore = true;
				mFresh = false;
				mRefresh = false;
				getPosts();
			}
			
		}
		
	});

P.s : I've set load more to scroll view, because recyclerview do it continuously and none stoppable!

Any help is appreciated

Android Solutions


Solution 1 - Android

This is because we have a recycler view which has scroll behaviour inside a scroll view. (scroll inside a scroll)

I think the best way to resolve this issue is to your profileCardview as a header in your recycler view and then remove the nested scroll view.

If it were a listview then it was as simple as listView.addHeaderView(profileCardView) but for the Recycler view there is no addheadview equivalent. Hence you could refer the below link to change your implementation.

https://stackoverflow.com/questions/26530685/is-there-an-addheaderview-equivalent-for-recyclerview

Solution 2 - Android

For a RecyclerView or ListView the height should be constant, because if it will not a constant size then how it will manage the maximum number of visible rows in memory. Try by changing RecyclerView attribute android:layout_height="match_parent" or a fixed height(e.g. "300dp" - as needed), instead of "wrap_content". It should improve your memory management.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMAY3AMView Question on Stackoverflow
Solution 1 - AndroidArpit RatanView Answer on Stackoverflow
Solution 2 - AndroidNeoView Answer on Stackoverflow