# Understand the RecyclerView Endless Scroll ## Using with LinearLayoutManager The logic for RecyclerView for `LinearLayoutManager` is implemented basically the same as what is used for the `ListView`. One slight difference from the `ListView` is that that the `RecyclerView` layout managers include the position of the last visible item on the screen, so we can use this info directly instead of needing to calculate it: ```java // This happens many times a second during a scroll, so be wary of the code you place here. // We are given a few useful parameters to help us work out if we need to load some more data, // but first we check if we are waiting for the previous load to finish. @Override public void onScrolled(RecyclerView view, int dx, int dy) { int lastVisibleItemPosition = mLinearLayoutManager.findLastVisibleItemPosition(); // ... ``` This position can the be used to calculate when new items need to be loaded by comparing the last visible position and the total number of items. ## Using with StaggeredGridLayoutManager Because the `StaggeredGridLayoutManager` enables elements to be placed in different columns, determining whether more items need to be loaded must be calculated by looking at the last visible positions across each row. We can implement endless scrolling by determining the highest value in the row to determine whether more items need to be fetched. Note also that the threshold value has to be increased since more items can be displayed on the screen, so we use a multiplier by calling [`getSpanCount()`](http://developer.android.com/reference/android/support/v7/widget/StaggeredGridLayoutManager.html#getSpanCount()) on the layout manager: ```java public abstract class EndlessRecyclerViewScrollListener extends RecyclerView.OnScrollListener { StaggeredGridLayoutManager mStaggeredGridLayoutManager; public EndlessRecyclerViewScrollListener(StaggeredGridLayoutManager layoutManager) { this.mStaggeredGridLayoutManager = layoutManager; visibleThreshold = visibleThreshold * mStaggeredGridLayoutManager.getSpanCount(); } public int getLastVisibleItem(int[] lastVisibleItemPositions) { int maxSize = 0; for (int i = 0; i < lastVisibleItemPositions.length; i++) { if (i == 0) { maxSize = lastVisibleItemPositions[i]; } else if (lastVisibleItemPositions[i] > maxSize) { maxSize = lastVisibleItemPositions[i]; } } return maxSize; } // This happens many times a second during a scroll, so be wary of the code you place here. // We are given a few useful parameters to help us work out if we need to load some more data, // but first we check if we are waiting for the previous load to finish. @Override public void onScrolled(RecyclerView view, int dx, int dy) { int[] lastVisibleItemPositions = mStaggeredGridLayoutManager.findLastVisibleItemPositions(null); lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions); int visibleItemCount = view.getChildCount(); int totalItemCount = mStaggeredGridLayoutManager.getItemCount(); // same code as before } } ``` ## Supporting Arbitrary Layout Managers The code used for the endless scrolling implements checks to determine which layout manager is being used: ```java public EndlessRecyclerViewScrollListener(LinearLayoutManager layoutManager) { this.mLayoutManager = layoutManager; } public EndlessRecyclerViewScrollListener(GridLayoutManager layoutManager) { this.mLayoutManager = layoutManager; // Increase visible threshold based on number of columns visibleThreshold = visibleThreshold * layoutManager.getSpanCount(); } public EndlessRecyclerViewScrollListener(StaggeredGridLayoutManager layoutManager) { this.mLayoutManager = layoutManager; // Increase visible threshold based on number of columns visibleThreshold = visibleThreshold * layoutManager.getSpanCount(); } ``` We can then calculate the last visible position depending on the layout manager: ```java @Override public void onScrolled(RecyclerView view, int dx, int dy) { int lastVisibleItemPosition = 0; int totalItemCount = mLayoutManager.getItemCount(); // Check the layout manager type in order to determine the last visible position if (mLayoutManager instanceof StaggeredGridLayoutManager) { int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(null); // get maximum element within the list lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions); } else if (mLayoutManager instanceof LinearLayoutManager) { lastVisibleItemPosition = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition(); } else if (mLayoutManager instanceof GridLayoutManager) { lastVisibleItemPosition = ((GridLayoutManager) mLayoutManager).findLastVisibleItemPosition(); } // Remaining scroll logic is here } ```