After scrolling to bottom of the RecyclerView, Data is fetched again from the Start which ultimately ends in infinite scrolling and never ends. I am using Firebase Realtime Database
This is my code :
String last_key = "", last_node = "";
boolean isMaxData = false, isScrolling = false;
int ITEM_LOAD_COUNT = 10;
int currentitems, tottalitems, scrolledoutitems;
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
isScrolling = true;
}
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
currentitems = manager.getChildCount();
tottalitems = manager.getItemCount();
scrolledoutitems = manager.findFirstVisibleItemPosition();
if (isScrolling && currentitems scrolledoutitems == tottalitems) {
// Toast.makeText(getContext(), "fetch data", Toast.LENGTH_SHORT).show();
isScrolling = false;
//fetch data
progressbar.setVisibility(View.VISIBLE);
Log.e("On","Scrolled, Reached Bottom");
getUsers();
}
}
});
This is how I am getting items from database :
private void getUsers() {
if (!isMaxData) // 1st fasle
{
Query query;
if (TextUtils.isEmpty(last_node))
query = FirebaseDatabase.getInstance().getReference("ShopCategories").child(recPosition).child("items")
.orderByKey()
.limitToFirst(ITEM_LOAD_COUNT);
else
query = FirebaseDatabase.getInstance().getReference("ShopCategories").child(recPosition).child("items")
.orderByKey()
.startAt(last_node)
.limitToFirst(ITEM_LOAD_COUNT);
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
if (snapshot.hasChildren()) {
List<TrendingModel> newUsers = new ArrayList<>();
for (DataSnapshot userSnapshot : snapshot.getChildren()) {
newUsers.add(userSnapshot.getValue(TrendingModel.class));
Log.e("NewUsersList","" userSnapshot.child("title").getValue(String.class));
}
// Log.e("NewUsersList","" newUsers);
last_node = newUsers.get(newUsers.size() - 1).getId(); //10 if it greater than the toatal items set to visible then fetch data from server
if (!last_node.equals(last_key))
newUsers.remove(newUsers.size() - 1); // 19,19 so to renove duplicate removeone value
else
last_node = "end";
// Toast.makeText(getContext(), "last_node" last_node, Toast.LENGTH_SHORT).show();
trendingAdapter.addAll(newUsers);
trendingAdapter.notifyDataSetChanged();
} else //reach to end no further child avaialable to show
{
isMaxData = true;
}
progressbar.setVisibility(View.GONE);
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
}
});
} else {
progressbar.setVisibility(View.GONE); //if data end
}
}
This is my code to get the Last Key from FirebaseRealtime Database :
private void getLastKeyFromFirebase() {
Query getLastKey = FirebaseDatabase.getInstance().getReference("ShopCategories").child(recPosition).child("items")
.orderByKey()
.limitToLast(1);
getLastKey.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for (DataSnapshot lastkey : snapshot.getChildren())
last_key = lastkey.getKey();
// Toast.makeText(getContext(), "last_key" last_key, Toast.LENGTH_SHORT).show();
Log.e("LastKey","" last_key);
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
Toast.makeText(CategoryDetailActivity.this, "can not get last key", Toast.LENGTH_SHORT).show();
}
});
}
This is the part of the Adapter class code : (not putting entire code, as it might get messy)
List<TrendingModel> trendingModelList;
Context context;
public TrendingAdapter(Context context) {
this.trendingModelList = new ArrayList<>();
Log.e("New","Instance creating");
this.context = context;
}
public void addAll(List<TrendingModel> newUsers) {
int initsize = trendingModelList.size();
trendingModelList.addAll(newUsers);
notifyItemRangeChanged(initsize, newUsers.size());
}
and the model class : (not putting entire code, as it might get messy):
public String getId() {
return id;
}
CodePudding user response:
You can either skip the duplicate item you get in your application code, or you can use the startAfter
operation instead of startAt
here:
query = FirebaseDatabase.getInstance().getReference("ShopCategories").child(recPosition).child("items")
.orderByKey()
.startAfter(last_node) //