I am using recycler view pagination to show my data. I am loading one page api data by default, for next page i am loading data on the scroll basis of the recycler view. But scroll is not getting called as i can see only 1 page. If i put the condition in on scroll for increasing page no. then on scroll method its not stopping & its calling api till last page in background. Meaning on scroll is calling again and again that I don't want. I want to scroll on basis of current visible items.
live_grid.addOnScrollListener(new PaginationScrollListener(gridLayoutManager) {
#Override
protected void loadMoreItems() {
// TODO: 07/11/16 check if totalPage > 1 before triggering next load
Log.d(TAG, "live_grid loadMoreItems.......");
int visibleItemCount = gridLayoutManager.getChildCount();
int totalItemCount = gridLayoutManager.getItemCount();
int firstVisibleItemPosition = gridLayoutManager.findFirstVisibleItemPosition();
Log.d(TAG, "visibleItemCount: "+ visibleItemCount);
Log.d(TAG, "totalItemCount: "+totalItemCount);
Log.d(TAG, "firstVisibleItemPosition: "+firstVisibleItemPosition);
Log.d(TAG, "currentPage: "+currentPage);
Log.d(TAG, "PAGE_SIZE: "+PAGE_SIZE);
if (!isLoading && !isLastPage) {
// if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount && firstVisibleItemPosition >= 0) {
if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount && firstVisibleItemPosition >= 0 && currentPage < (PAGE_SIZE)) {
//&& totalItemCount >= PAGE_SIZE
firstVisibleItemPosition = visibleItemCount;
loadMoreItems1();
}
}
// presenter.setIsLoading(true);
// presenter.setCurrentPage(presenter.getCurrentPage() + 1);
// presenter.loadNextPlaylist();
}
Try this code..
protected int pastVisibleItems, visibleItemCount, totalItemCount; // define class level..
protected void addScrollListener() {
rvData.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (dy > 0) //check for scroll down
{
visibleItemCount = linearLayoutManager.getChildCount();
totalItemCount = linearLayoutManager.getItemCount();
pastVisibleItems = linearLayoutManager.findFirstVisibleItemPosition();
if ((visibleItemCount + pastVisibleItems) >= totalItemCount) {
pageNumber++; // increase your page
getMessage(); // call api with new Page.
}
}
}
});
}
this method used after recyclerview define and bind adapter.
GridLayoutManger..
RecyclerView.OnScrollListener scrollListener = new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int totalItrem = mLlManager.getItemCount();
int lastViisble = mLlManager.findLastVisibleItemPosition();
Log.d("item", "total item" + totalItrem);
Log.d("visible", "last " + lastViisble);
if (!isLoading && totalItrem == lastViisble + 1 && total_records != mEventList.size()) {
Log.e("msg", "reached end");
//Toast.makeText(mrecyclerview.getContext(), "reached at end", Toast.LENGTH_SHORT).show();
isLoading = true;
mEventList.add(null);
mCurrentPage++;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
getData(mCurrentPage);
}
}, 2000);
}
}
};
Related
My recyclerview.Onscrolled() method is getting called only once.
When I am trying to scroll down, it not getting scrolled and onSCrolled method is not getting called
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
boolean loading = true;
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy)
{
if (loading) {
if (dy > 0) //check for scroll down
{
int visibleItemCount = 6;
int totalItemCount = posts.size();
int pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition();
if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
loading = false;
Log.v("...", " Reached Last Item");
int size = mAdapter.getTodoList().size();
mAdapter.getTodoList().clear();
mAdapter.setTodoList(getNextItems(mAdapter.getResult(),size));
mAdapter.notifyItemRangeInserted(size, mAdapter.getTodoList().size() - 1);
}
}
}
}
});
I'm trying to implement pagination using code below, and it work well with fragments, but when i implemented it in Nested Fragment it load all data (load first page and all next pages continuously). The problem is that my total items is 12 and visible in time is 3 but layoutManager.getChildCount() give me 12 same as total item (layoutManager.getItemCount()) so it start loading next pages continuously.
Here is oNScroll code :
public PaginationScrollListener(LinearLayoutManager layoutManager) {
this.layoutManager = layoutManager;
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int visibleItemCount = layoutManager.getChildCount();
int totalItemCount = layoutManager.getItemCount();
int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
if (!isLoading() && !isLastPage()) {
if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount
&& firstVisibleItemPosition >= 0
&& totalItemCount >= getTotalPageCount()) {
loadMoreItems();
}
}
}
When scroll and request next pages :
recyclerView.addOnScrollListener(new PaginationScrollListener(layoutManager) {
#Override
protected void loadMoreItems() {
isLoading = true;
currentPage += 1;
// mocking network delay for API call
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
loadNextPage();
}
}, 1000);
}
#Override
public int getTotalPageCount() {
return TOTAL_PAGES;
}
#Override
public boolean isLastPage() {
return isLastPage;
}
#Override
public boolean isLoading() {
return isLoading;
}
});
change your scroll listener like below:
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if(dy>0){ //if is scrolling vertically
int visibleItemCount = layoutManager.getChildCount();
int totalItemCount = layoutManager.getItemCount();
int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
if (!isLoading() && !isLastPage()) {
if (firstVisibleItemPosition + visibleItemCount >= totalItemCount) {
//make your request here
}
}
}});
I am using a Recyclerview with StaggeredGridLayoutManager with Endless Scroll. I want to do a network call when the last item of the list is visible to the user. So here is my code:
public RecyclerViewAdapter(Context context) {
Log.d(Const.DEBUG, "RecyclerViewAdapter Constructor()");
this.context = context;
final StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) recyclerView.getLayoutManager();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
totalItemCount = staggeredGridLayoutManager.getItemCount();
lastVisibleItems = staggeredGridLayoutManager.findLastVisibleItemPositions(new int[mStaggeredLayoutManager.getSpanCount()]);
Log.d(Const.DEBUG, "LastVisibleItems: " + Arrays.toString(lastVisibleItems));
Log.d(Const.DEBUG, "LastVisibleItems Count: " + lastVisibleItems.length);
if (staggeredGridLayoutManager.getSpanCount() == 1) {
lastVisibleItem = lastVisibleItems[0];
} else if (staggeredGridLayoutManager.getSpanCount() == 2) {
lastVisibleItem = Math.max(lastVisibleItems[0], lastVisibleItems[1]);
} else if (staggeredGridLayoutManager.getSpanCount() == 3) {
lastVisibleItem = Math.max(Math.max(lastVisibleItems[0], lastVisibleItems[1]), lastVisibleItems[2]);
}
if (!isRefreshing && (totalItemCount <= lastVisibleItem + visibleThreshold)) {
Log.d(Const.DEBUG, "isRefreshing: " + isRefreshing);
Log.d(Const.DEBUG, "totalItemCount: " + totalItemCount);
Log.d(Const.DEBUG, "lastVisibileItem: " + lastVisibleItem);
Log.d(Const.DEBUG, "visibileThreshold: " + visibleThreshold);
Log.d(Const.DEBUG, "calling LoadMore()");
if (mIOnLoadMoreListener != null) {
mIOnLoadMoreListener.onLoadMore();
}
isRefreshing = true;
}
}
});
}
I get 9 values from server on first call. So, when i move to the last index[8], the lastVisibleItem will be 8 and visibleThreshold is 1, totalItemCount is 9 and so the next network call should happen. What is actually happening now, is, when the screen loads for the first time, the lastVisibleItem should be 1 or 2, but its returning 8, and as a result, the loadMore() is getting called.
Logcat:
D/xx: Items Count: 9
D/xx: LastVisibleItems: [8]
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: LastVisibleItems Count: 1
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: isRefreshing: false
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: totalItemCount: 9
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: lastVisibileItem: 8
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: visibileThershold: 1
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: calling LoadMore()
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: onLoadMore()
03-22 15:22:52.798 5957-5957/codsiga.com.xx D/xx: getDataFromServer()
What is wrong in the above code? Let me know if you need anything else. The same code worked well before.
Try this.
private int pastVisiblesItems, visibleItemCount, totalItemCount;
private boolean loading = true;
private StaggeredGridLayoutManager layoutManager;
private RecyclerView recyclerView ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layoutManager=new StaggeredGridLayoutManager(2,1);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(layoutManager);
recycleView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (dy > 0) //for vertical scrolling
{
} else if (dy < 0) {
}
if (dx > 0)//for horizontal scrolling
{
visibleItemCount = layoutManager.getChildCount();
totalItemCount = layoutManager.getItemCount();
pastVisiblesItems = layoutManager.findFirstVisibleItemPosition();
if (loading) {
if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
loading = false;
loadMore(); //desired function call
}
}
}
}
});
}
Please don't forget to make loading=true after the success of API calling.
Hope it may help..
following code is work for me :
//return true if it's last item visited
private boolean isLastItemDisplaying(RecyclerView recyclerView) {
if (recyclerView.getAdapter().getItemCount() != 0) {
//int lastVisibleItemPosition = ((StaggeredGridLayoutManager)recyclerView.getLayoutManager()).findLastVisibleItemPositions();
int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) Objects.requireNonNull(recyclerView.getLayoutManager())).findLastVisibleItemPositions(null);
// get maximum element within the list
int lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions);
return lastVisibleItemPosition != RecyclerView.NO_POSITION && lastVisibleItemPosition == recyclerView.getAdapter().getItemCount() - 1;
}
return false;
}
//get last item
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;
}
private void recyclerViewOnScroll(RecyclerView recyclerView, final StaggeredGridLayoutManager staggeredGridLayoutManager) {
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dy > 0) {
totalItemCount = staggeredGridLayoutManager.getItemCount();
if (lastPositions == null)
lastPositions = new int[staggeredGridLayoutManager.getSpanCount()];
lastPositions = staggeredGridLayoutManager.findLastCompletelyVisibleItemPositions(lastPositions);
lastVisibleItem = Math.max(lastPositions[0], lastPositions[1]);//findMax(lastPositions);
if (!loading && totalItemCount >= 20 && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
// End has been reached
if (onLoadMoreListener != null) {
onLoadMoreListener.onLoadMore();
}
loading = true;
}
}
}
});
}
I have RecycleView which showing the number of items with admob it is working good but i want to implement pagination functionality, i have tried to implement but i didn't get success, My code is like below
Home.Java
recycleFeedList.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (dy > 0) //check for scroll down
{
visibleItemCount = mLinearLayoutManager.getChildCount();
totalItemCount = mLinearLayoutManager.getItemCount();
pastVisiblesItems = mLinearLayoutManager.findFirstVisibleItemPosition();
if (loading) {
LogUtils.LOGD("LastPage:", lastPage + "");
LogUtils.LOGD("visibleItemCount:", visibleItemCount + "");
LogUtils.LOGD("pastVisiblesItems:", pastVisiblesItems + "");
LogUtils.LOGD("totalItemCount:", totalItemCount + "");
if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
loading = false;
getFeedList(2, "", 1, lastPage);
}
}
}
}
});
and my adapter is like below:
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
RecyclerViewFeedItem recyclerViewFeedItem = (RecyclerViewFeedItem) viewHolder.itemView;
recyclerViewFeedItem.bind(mContext, items, position, this, REQUEST_CODE);
}
You can do it like this:
int currentPage = 1;
class OnScrollListener extends RecyclerView.OnScrollListener
{
int firstVisibleItem;
int visibleItemCount;
int totalItemCount;
private int previousTotal = 0;
private boolean loading = true;
private int visibleThreshold = 5;
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy)
{
if (dy > 0)
{
visibleItemCount = layoutManager.getChildCount();
totalItemCount = layoutManager.getItemCount();
firstVisibleItem = layoutManager.findFirstVisibleItemPosition();
if (loading)
{
if (totalItemCount > previousTotal)
{
loading = false;
previousTotal = totalItemCount;
}
}
if (!loading &&
(totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold))
{
currentPage++;
//here you load next page, e.g.: load(currentPage);
footer.setVisibility(View.VISIBLE);
loading = true;
}
}
}
}
Usage:
recyclerView.addOnScrollListener(new OnScrollListener());
I implement the following code. It works, but I retrieve it more tha once, it makes many duplication in my data. How do I make it to run the retrieve more data just once?
final LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager();
recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
boolean loading = true;
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
int pastVisibleItems, visibleItemCount, totalItemCount;
visibleItemCount = layoutManager.getChildCount();
totalItemCount = layoutManager.getItemCount();
pastVisibleItems = layoutManager.findFirstVisibleItemPosition();
if (loading) {
if ((visibleItemCount + pastVisibleItems) >= totalItemCount) {
loading = false;
//retrieve more data from internet
loading = true;
}
}
}
});
It turns out below algorithm is better
private int previousTotal = 0;
private boolean loading = true;
private int visibleThreshold = 5;
int firstVisibleItem, visibleItemCount, totalItemCount;
mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = mRecyclerView.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
}
}
if (!loading && (totalItemCount - visibleItemCount)
<= (firstVisibleItem + visibleThreshold)) {
// End has been reached
Log.i("...", "end called");
// Do something
loading = true;
}
}
});
source