# 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
}
```