Firebase Realtime Database Pagination in Recyclerview
3 min readOct 2, 2020
pagination is also known as load more functionality or infinite loading
We can both implement Linealayout or Grid Layout.
I am using a fragment to implementing this but you can do with activity also.
UsersFragment.Java
public class UserFragment extends Fragment
{
View UserFragment;
RecyclerView recycler_view_user;
// LinearLayoutManager manager; //for linear layout
NewAdapter adapter;
String last_key="",last_node="";
boolean isMaxData=false,isScrolling=false;
int ITEM_LOAD_COUNT= 10;
ProgressBar progressBar;
int currentitems,tottalitems,scrolledoutitems;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
{
UserFragment=inflater.inflate(R.layout.fragment_user,container,false);
recycler_view_user=UserFragment.findViewById(R.id.recycler_view_user);
progressBar=UserFragment.findViewById(R.id.progressBar1);
getLastKeyFromFirebase(); //43
// manager=new LinearLayoutManager(getContext());
GridLayoutManager manager = new GridLayoutManager(getContext(),2); //for grid layout
adapter=new NewAdapter(getContext());
recycler_view_user.setAdapter(adapter);
recycler_view_user.setLayoutManager(manager);
getUsers();
recycler_view_user.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);
getUsers();
}
}
});
return UserFragment;
}
private void getUsers()
{
if(!isMaxData) // 1st fasle
{
Query query;
if (TextUtils.isEmpty(last_node))
query = FirebaseDatabase.getInstance().getReference()
.child("Users")
.orderByKey()
.limitToFirst(ITEM_LOAD_COUNT);
else
query = FirebaseDatabase.getInstance().getReference()
.child("Users")
.orderByKey()
.startAt(last_node)
.limitToFirst(ITEM_LOAD_COUNT);
query.addListenerForSingleValueEvent(new ValueEventListener()
{
@Override
public void onDataChange(@NonNull DataSnapshot snapshot)
{
if(snapshot.hasChildren())
{
List<Users> newUsers = new ArrayList<>();
for (DataSnapshot userSnapshot : snapshot.getChildren())
{
newUsers.add(userSnapshot.getValue(Users.class));
}
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();
adapter.addAll(newUsers);
adapter.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
}
}
private void getLastKeyFromFirebase()
{
Query getLastKey= FirebaseDatabase.getInstance().getReference()
.child("Users")
.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();
}
@Override
public void onCancelled(@NonNull DatabaseError error)
{
Toast.makeText(getContext(), "can not get last key", Toast.LENGTH_SHORT).show();
}
});
}
}
UsersFragment.Xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view_user"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
/>
<ProgressBar
android:id="@+id/progressBar1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:visibility="gone"
/>
</RelativeLayout>
NewAdapter.Java
public class NewAdapter extends RecyclerView.Adapter<NewAdapter.NewViewHolder>
{
List<Users> usersList;
Context context;
public NewAdapter( Context context)
{
this.usersList = new ArrayList<>();
this.context = context;
}
public void addAll(List<Users> newUsers)
{
int initsize=usersList.size();
usersList.addAll(newUsers);
notifyItemRangeChanged(initsize,newUsers.size());
}
public static class NewViewHolder extends RecyclerView.ViewHolder
{
TextView name;
public NewViewHolder(@NonNull View itemView)
{
super(itemView);
name=itemView.findViewById(R.id.name);
}
}
@NonNull
@Override
public NewViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
{
View itemView= LayoutInflater.from(context).inflate(R.layout.user_layout_items,parent,false);
return new NewViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull NewViewHolder holder, int position)
{
holder.name.setText(usersList.get(position).getName());
}
@Override
public int getItemCount()
{
return usersList.size();
}
}
ModelClass
Users.java
package com.xscroll.infinitescroll.Model;
public class Users
{
private String id,name,email;
public Users()
{
}
public Users(String id, String name, String email)
{
this.id = id;
this.name = name;
this.email = email;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Result: