Paganizing Firebase Lampshades

I am creating an application that will show the video stored on firebase. The list of videos should be paginated, getting the last 20 videos at a time.

enter image description here

Here is the code that I thought would work

private void getVideos() { Query videosQuery = FirebaseUtil.getVideosRef(); videosQuery.startAt(0); videosQuery.endAt(1); ChildEventListener videosChildEventListener = new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { String date = dataSnapshot.getKey(); String temp = date; } @Override public void onChildChanged(DataSnapshot dataSnapshot, String s) { } @Override public void onChildRemoved(DataSnapshot dataSnapshot) { } @Override public void onChildMoved(DataSnapshot dataSnapshot, String s) { } @Override public void onCancelled(DatabaseError databaseError) { Log.d(tag, "database error"); } }; ValueEventListener videoValueEventListener = new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { String date = dataSnapshot.getKey(); String temp = date; long count = dataSnapshot.getChildrenCount(); String value = dataSnapshot.getValue().toString(); temp = value; } @Override public void onCancelled(DatabaseError databaseError) { Log.d(tag, "database error"); } }; // videosQuery.addChildEventListener(videosChildEventListener); videosQuery.addValueEventListener(videoValueEventListener); } 

But the above code retrieves the entire list of videos instead of limited videos. How pagination can be done.

+16
android android-recyclerview firebase firebase-database firebase-realtime-database
source share
9 answers

Below is the code that I use for pagination, which shows the last node.

  public void getImages() { Query imagesQuery = FirebaseDatabase.getInstance().getReference().child("englishDps").child(mChildName).orderByKey().limitToLast(21); ChildEventListener childEventListener = new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { Image image = dataSnapshot.getValue(Image.class); image.setNodeKey(dataSnapshot.getKey()); mTempImages.add(image); if (mTempImages.size() == 21) { mLastKey = mTempImages.get(0).getNodeKey(); Collections.reverse(mTempImages); mTempImages.remove(mTempImages.size() - 1); mImages.addAll(mTempImages); setAdapter(); } } @Override public void onChildChanged(DataSnapshot dataSnapshot, String s) { } @Override public void onChildRemoved(DataSnapshot dataSnapshot) { } @Override public void onChildMoved(DataSnapshot dataSnapshot, String s) { } @Override public void onCancelled(DatabaseError databaseError) { if (isAdded()) { Toast.makeText(getActivity(), "Problem loading more images...", Toast.LENGTH_LONG).show(); } } }; imagesQuery.addChildEventListener(childEventListener); } @Override public void getMoreImages() { if (!mGettingMoreImages) { mGettingMoreImages = true; Query imagesQuery = FirebaseDatabase.getInstance().getReference("englishDps").child(mChildName).orderByKey().endAt(mLastKey).limitToLast(21); ChildEventListener childEventListener = new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { Image image = dataSnapshot.getValue(Image.class); image.setNodeKey(dataSnapshot.getKey()); mMoreImages.add(image); if (mMoreImages.size() == 21) { mLastKey = mMoreImages.get(0).getNodeKey(); Collections.reverse(mMoreImages); mMoreImages.remove(mMoreImages.size() - 1); mImages.addAll(mMoreImages); mMoreImages.clear(); mGettingMoreImages = false; mImagesAdapter.notifyDataSetChanged(); return; } if (mLastKey.equalsIgnoreCase(image.getNodeKey())) { Collections.reverse(mMoreImages); mImages.addAll(mMoreImages); mMoreImages.clear(); mGettingMoreImages = false; mImagesAdapter.onNoMoreImages(); ; mImagesAdapter.notifyDataSetChanged(); } } @Override public void onChildChanged(DataSnapshot dataSnapshot, String s) { } @Override public void onChildRemoved(DataSnapshot dataSnapshot) { } @Override public void onChildMoved(DataSnapshot dataSnapshot, String s) { } @Override public void onCancelled(DatabaseError databaseError) { if (isAdded()) { Toast.makeText(getActivity(), "Problem loading more images...", Toast.LENGTH_LONG).show(); } } }; imagesQuery.addChildEventListener(childEventListener); } } 
+14
source share

You want to use the limitToFirst / limitToLast methods to get a limited number of results.

 videosQuery.orderByKey().limitToFirst(20) 

https://www.firebase.com/docs/web/api/query/limittofirst.html

You should consider changing the naming convention of your videos to include leading 0 (i.e. video01, video02 ... video10, video11), because the above code will display them exactly the same as yours above (which I assume order?)

Alternatively, if you are adding video via Java, you can simply let firebase create unique objects using push (). Unique ones are generated in such a way that they will be sorted chronically, which sounds like it suits you to capture the most recent videos (added?).

https://www.firebase.com/docs/web/api/firebase/push.html

+4
source share
  mPageEndOffset = 0; mPageLimit = 10; mPageEndOffset += mPageLimit; deviceListQuery = mDatabase.child("users") .orderByChild("id").limitToFirst(mPageLimit).startAt(mPageEndOffset); deviceListQuery.addValueEventListener(YourActivity.this); 
+4
source share

I have the following pagination method through the firebase node real-time database:

 private void getUsers(String nodeId) { Query query; if (nodeId == null) query = FirebaseDatabase.getInstance().getReference() .child(Consts.FIREBASE_DATABASE_LOCATION_USERS) .orderByKey() .limitToFirst(mPostsPerPage); else query = FirebaseDatabase.getInstance().getReference() .child(Consts.FIREBASE_DATABASE_LOCATION_USERS) .orderByKey() .startAt(nodeId) .limitToFirst(mPostsPerPage); query.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { UserModel user; List<UserModel> userModels = new ArrayList<>(); for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) { userModels.add(userSnapshot.getValue(UserModel.class)); } mAdapter.addAll(userModels); mIsLoading = false; } @Override public void onCancelled(DatabaseError databaseError) { mIsLoading = false; } }); } 

Each time I get to the bottom of the paginated data, I call getUsers(mAdapter.getLastItemId()); , and then displays the next set of records.

I wrote a complete guide using an open source application that you can check at https://blog.shajeelafzal.com/2017/12/13/firebase-realtime-database-pagination-guide-using-recyclerview/

+4
source share

Since this question regarding the implementation of Pagination for the Firestore request is marked as a duplicate of this question, I will answer it here.

Paginate request on android Firestore

 Query query = db.collection("cities") .orderBy("population") .limit(25); Query next = query; private void loadCities() { query = next; query.get() .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() { @Override public void onSuccess(QuerySnapshot documentSnapshots) { // Get the last visible document DocumentSnapshot lastVisible = documentSnapshots.getDocuments() .get(documentSnapshots.size() -1); // Construct a new query starting at this document, // get the next 25 cities. next = db.collection("cities") .orderBy("population") .startAfter(lastVisible) .limit(25); } }); } 

Now just call the loadCities() method whenever you need to load more cities.

+1
source share

This is how I applied pagination from the firebase database. Consider the case if we have 100 posts. Therefore, I first load the last 20 messages from firebase, that is, from 81 to 100. Then, when scrolling up, I call the getMoreMessages() function to load the next 20 messages, which are from 61 to 80, etc.

 public class ChatActivity extends Activity { String chat_id = ""; long mTotalChildren = 0; boolean loading = false; ChildEventListener childEventListenerMain, childEventListenerPager; ChatActivity mContext = ChatActivity.this; MessageAdapter messageAdapter; @BindView(R.id.pb_messages) ProgressBar pb_messages; @BindView(R.id.ll_audio) LinearLayout llAudio; @BindView(R.id.tv_record_time) AppCompatTextView tvRecordTime; @BindView(R.id.tv_cancel) AppCompatTextView tvCancel; @BindView(R.id.iv_send) AppCompatImageView ivSend; @BindView(R.id.iv_record) AppCompatImageView ivRecord; @BindView(R.id.ab_layout) AppBarLayout abLayout; @BindView(R.id.messages) RecyclerView rvMessages; @BindView(R.id.iv_chat_icon) SimpleDraweeView ivChatIcon; @BindView(R.id.iv_camera) AppCompatImageView ivCamera; @BindView(R.id.iv_gallery) AppCompatImageView ivGallery; @BindView(R.id.message_input) AppCompatEditText messageInput; @BindView(R.id.tv_send) AppCompatTextView tvSend; @BindView(R.id.toolbar_title) AppCompatTextView toolbarTitle; @BindView(R.id.toolbar_status) AppCompatTextView toolbarStatus; @BindView(R.id.ll_send) LinearLayout llSend; int categoryId, senderId, receiverId, offerId; String mLastKey; LinearLayoutManager layoutManager; private ArrayList<MessageModel> messageArrayList = new ArrayList<>(); private ArrayList<MessageModel> tempMessageArrayList = new ArrayList<>(); @Override public int getLayoutId() { return R.layout.activity_chat; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); messageAdapter = new MessageAdapter(mContext, messageArrayList) { }; layoutManager = new LinearLayoutManager(mContext); rvMessages.setLayoutManager(layoutManager); rvMessages.setItemAnimator(new DefaultItemAnimator()); rvMessages.setAdapter(messageAdapter); rvMessages.setHasFixedSize(true); rvMessages.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); if (messageArrayList.size() >= 20 && !loading && layoutManager.findFirstVisibleItemPosition() == 0 && messageArrayList.size() < mTotalChildren) { loading = true; getMoreMessages(); } } }); messageAdapter.notifyDataSetChanged(); //used to scroll up recyclerview when keyboard pops up rvMessages.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View view, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { if (bottom < oldBottom) { rvMessages.postDelayed(new Runnable() { @Override public void run() { rvMessages.scrollToPosition(messageArrayList.size() - 1); } }, 100); } } }); loading = true; getMessages(); } public void getMessages() { FirebaseDatabase.getInstance().getReference().child(pathtomsgs).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { Log.e("childrenCount", String.valueOf(+dataSnapshot.getChildrenCount())); mTotalChildren = dataSnapshot.getChildrenCount(); } @Override public void onCancelled(DatabaseError databaseError) { } }); Query messageQuery = FirebaseDatabase.getInstance().getReference().child(pathtomsgs).limitToLast(20); childEventListenerMain = new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { loading = true; MessageModel messageModel = dataSnapshot.getValue(MessageModel.class); if (messageModel != null) { messageModel.chat_id = chat_id; messageModel.message_id = dataSnapshot.getKey(); messageArrayList.add(messageModel); messageAdapter.notifyDataSetChanged(); mLastKey = messageArrayList.get(0).message_id; rvMessages.scrollToPosition(messageArrayList.size() - 1); } } @Override public void onChildChanged(DataSnapshot dataSnapshot, String s) { } @Override public void onChildRemoved(DataSnapshot dataSnapshot) { } @Override public void onChildMoved(DataSnapshot dataSnapshot, String s) { } @Override public void onCancelled(DatabaseError databaseError) { Toast.makeText(mContext, "Problem loading more images...", Toast.LENGTH_LONG).show(); } }; messageQuery.addChildEventListener(childEventListenerMain); ValueEventListener messageChildSINGLEValueEventListener = new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { pb_messages.setVisibility(View.GONE); System.out.println("We're done loading messages " + dataSnapshot.getChildrenCount() + " items"); loading = false; } @Override public void onCancelled(DatabaseError databaseError) { } }; messageQuery.addListenerForSingleValueEvent(messageChildSINGLEValueEventListener); } public void getMoreMessages() { tempMessageArrayList.clear(); Query messageQuery = FirebaseDatabase.getInstance().getReference().child(pathtomsgs).orderByKey().endAt(mLastKey).limitToLast(20); childEventListenerPager = new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { loading = true; MessageModel messageModel = dataSnapshot.getValue(MessageModel.class); if (messageModel != null) { messageModel.chat_id = chat_id; messageModel.message_id = dataSnapshot.getKey(); tempMessageArrayList.add(messageModel); } } @Override public void onChildChanged(DataSnapshot dataSnapshot, String s) { } @Override public void onChildRemoved(DataSnapshot dataSnapshot) { } @Override public void onChildMoved(DataSnapshot dataSnapshot, String s) { } @Override public void onCancelled(DatabaseError databaseError) { Toast.makeText(mContext, "Problem loading more images...", Toast.LENGTH_LONG).show(); } }; messageQuery.addChildEventListener(childEventListenerPager); ValueEventListener messageChildSINGLEValueEventListener = new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { System.out.println("We're done loading messages " + dataSnapshot.getChildrenCount() + " items"); tempMessageArrayList.remove(tempMessageArrayList.size() - 1); messageArrayList.addAll(0, tempMessageArrayList); mLastKey = messageArrayList.get(0).message_id; messageAdapter.notifyDataSetChanged(); //rvMessages.scrollToPosition(20); layoutManager.scrollToPositionWithOffset(19, 0); loading = false; } @Override public void onCancelled(DatabaseError databaseError) { } }; messageQuery.addListenerForSingleValueEvent(messageChildSINGLEValueEventListener); } @Override protected void onDestroy() { FirebaseDatabase.getInstance().getReference().child(pathtomsgs).removeEventListener(childEventListenerPager); FirebaseDatabase.getInstance().getReference().child(pathtomsgs).removeEventListener(childEventListenerMain); super.onDestroy(); } } 
0
source share

The Android paging library can be used to implement pagination for data retrieved from the firebase database. Data is displayed in recycler mode, and the paging component selects pages in response to user scroll events.

The paging data source calls your Firebase object's DAO object, passing the request parameters for the page to be displayed, and the results are passed back to the paging component using the callback provided to it.

Here is a complete link example http://www.zoftino.com/firebase-pagination-using-android-paging-library

0
source share

the accepted answer does not work when less than max. itmes (21) in the database. this is my solution based on accepted answer:

0) set variables

  private String lastMessageKey; private int totalItemCount; private int lastVisibleItem; private boolean isLoadingMoreFollowers = false; private boolean hasMoreItems = true; private boolean hasShownNoMoreItemsToast = false; private boolean initialLoad = true; private final int MAX_LOAD_ITEMS = 11; private final int VISIBLE_TRESHOLD = 1; 

1) set the listener:

  private void setMessageListener() { if (childEventListener == null) { mmessageArrayList.clear(); final ArrayList<Mmessage> tempMmessages = new ArrayList<>(); query = mDatabaseInstace.getReference().child(chat1).child(F.CHATS).child(F.MESSAGES).orderByKey().limitToLast(MAX_LOAD_ITEMS-1); childEventListener = new ChildEventListener() { @Override public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) { Log.d(TAG, "onChildAdded: -----------------> " + dataSnapshot); Log.d(TAG, "onChildAdded: -----------------> " + s); tempMmessages.add(dataSnapshot.getValue(Mmessage.class)); preloadMessagePics(tempMmessages); if (initialLoad) { lastMessageKey = tempMmessages.get(0).getMessagePushKey(); initialLoad = false; } mmessageArrayList.add(tempMmessages.size()-1, tempMmessages.get(0)); messageAdapter.notifyDataSetChanged(); tempMmessages.clear(); } @Override public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) { Log.d(TAG, "onChildChanged: --------------------------------->"); } @Override public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) { Log.d(TAG, "onChildRemoved: ---------------------------------->"); } @Override public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) { Log.d(TAG, "onChildMoved: ------------------------------------>"); } @Override public void onCancelled(@NonNull DatabaseError databaseError) { Log.d(TAG, "onCancelled: ------------------------------------->"); } }; query.addChildEventListener(childEventListener); } } 

2) set the download of another listener:

  private void setLoadMoreListener(){ setup.RV_messages.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); totalItemCount = linearLayoutManager.getItemCount(); lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition(); if (!isLoadingMoreFollowers && totalItemCount <= (lastVisibleItem+VISIBLE_TRESHOLD) && (totalItemCount >= MAX_LOAD_ITEMS-1)){ if (hasMoreItems) { getMoreMessages(); Toast.makeText(homeActivity, "load more items", Toast.LENGTH_SHORT).show(); }else { if (!hasShownNoMoreItemsToast) { Toast.makeText(homeActivity, "has no more items", Toast.LENGTH_SHORT).show(); hasShownNoMoreItemsToast = true; } } } } }); } 

3) get more items:

  private void getMoreMessages(){ final ArrayList<Mmessage> tempMmessages = new ArrayList<>(); isLoadingMoreFollowers = true; loadMoreQuery = mDatabaseInstace.getReference().child(chat1).child(F.CHATS).child(F.MESSAGES).orderByKey().endAt(lastMessageKey).limitToLast(MAX_LOAD_ITEMS); loadMoreChildEventListener = new ChildEventListener() { @Override public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) { tempMmessages.add(dataSnapshot.getValue(Mmessage.class)); preloadMessagePics(tempMmessages); if (tempMmessages.size() == MAX_LOAD_ITEMS){ lastMessageKey = tempMmessages.get(0).getMessagePushKey(); Collections.reverse(tempMmessages); tempMmessages.remove(0); mmessageArrayList.addAll(tempMmessages); isLoadingMoreFollowers = false; messageAdapter.notifyDataSetChanged(); tempMmessages.clear(); return; } if (lastMessageKey.equalsIgnoreCase(tempMmessages.get(tempMmessages.size()-1).getMessagePushKey())){ Collections.reverse(tempMmessages); tempMmessages.remove(0); mmessageArrayList.addAll(tempMmessages); isLoadingMoreFollowers = false; hasMoreItems = false; messageAdapter.notifyDataSetChanged(); tempMmessages.clear(); } } @Override public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) { } @Override public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) { } @Override public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) { } @Override public void onCancelled(@NonNull DatabaseError databaseError) { } }; loadMoreQuery.addChildEventListener(loadMoreChildEventListener); } 

have fun !!

0
source share

You can achieve this using the Firebase database swap library, as shown below: ... In this code, I showed Post as an element of the data model and PostViewHolder as ViewHolder

  //Initialize RecyclerView mRecyclerView = findViewById(R.id.recycler_view); mRecyclerView.setHasFixedSize(true); LinearLayoutManager mManager = new LinearLayoutManager(this); mRecyclerView.setLayoutManager(mManager); //Initialize Database mDatabase = FirebaseDatabase.getInstance().getReference().child("posts"); //Initialize PagedList Configuration PagedList.Config config = new PagedList.Config.Builder() .setEnablePlaceholders(false) .setPrefetchDistance(5) .setPageSize(10) .build(); //Initialize FirebasePagingOptions DatabasePagingOptions<Post> options = new DatabasePagingOptions.Builder<Post>() .setLifecycleOwner(this) .setQuery(mDatabase, config, Post.class) .build(); //Initialize Adapter mAdapter = new FirebaseRecyclerPagingAdapter<Post, PostViewHolder>(options) { @NonNull @Override public PostViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { return new PostViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false)); } @Override protected void onBindViewHolder(@NonNull PostViewHolder holder, int position, @NonNull Post model) { holder.setItem(model); } @Override protected void onLoadingStateChanged(@NonNull LoadingState state) { switch (state) { case LOADING_INITIAL: case LOADING_MORE: // Do your loading animation mSwipeRefreshLayout.setRefreshing(true); break; case LOADED: // Stop Animation mSwipeRefreshLayout.setRefreshing(false); break; case FINISHED: //Reached end of Data set mSwipeRefreshLayout.setRefreshing(false); break; case ERROR: retry(); break; } } @Override protected void onError(@NonNull DatabaseError databaseError) { super.onError(databaseError); mSwipeRefreshLayout.setRefreshing(false); databaseError.toException().printStackTrace(); } }; //Set Adapter to RecyclerView mRecyclerView.setAdapter(mAdapter); 

Just visit this URL below for the link https://firebaseopensource.com/projects/patilshreyas/firebaserecyclerpagination/app/readme.md/ Here you will find the library implementation that helps implement Firebase pagination in RecyclerView

I hope this helps you!

0
source share

All Articles