Firebase android pagination

后端 未结 10 1499
天命终不由人
天命终不由人 2020-11-28 09:14

I\'m building an app which will show videos stored on firebase. The list of videos needs to be paginated fetching most recent 20 videos at a time.

Here is

相关标签:
10条回答
  • 2020-11-28 09:17

    Below is the code I'm using for pagination which shows the latest node first.

          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);
            }
        }
    
    0 讨论(0)
  • 2020-11-28 09:20

    If you want to get list from firebase realtime database descending with pagination you need use smth like this:

    Query query = myRef.child("stories").orderByChild("takenAt").endAt(1600957136000L).limitToLast(30);
    

    Full code, two requests

            List<Story> storyList = new ArrayList<>();
            
            FirebaseDatabase database = FirebaseDatabase.getInstance();
            DatabaseReference myRef = database.getReference();
            
            //first request will be look like this
            Query query = myRef.child("stories").orderByChild("takenAt").endAt(1600957136000L).limitToLast(30);
            query.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                    if (dataSnapshot.exists()) {
                        for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                            Story story = snapshot.getValue(Story.class);
                            storyList.add(story);
                        }
                    }
                    Collections.reverse(storyList);
                }
                @Override
                public void onCancelled(@NonNull DatabaseError error) {
                    Log.e("ptg", "onCancelled: ", error.toException());
                }
            });
            
            //second request
            long lastTakenAtInTheStoryList = storyList.get(storyList.size()-1).getTakenAt();
            Query query2 = myRef.child("stories").orderByChild("takenAt").endAt(lastTakenAtInTheStoryList).limitToLast(30);
            query2.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                    if (dataSnapshot.exists()) {
                        for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                            Story story = snapshot.getValue(Story.class);
                            storyList.add(story);
                        }
                    }
                    Collections.reverse(storyList);
                }
                @Override
                public void onCancelled(@NonNull DatabaseError error) {
                    Log.e("ptg", "onCancelled: ", error.toException());
                }
            });
    
    0 讨论(0)
  • 2020-11-28 09:21

    I have following method to paginate through a firebase realtime database node:

    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;
                }
            });
        }
    

    Every time I reach the bottom of the paginated data, I call the getUsers(mAdapter.getLastItemId()); and then it brings the next set of records.

    I have written a complete guide with open source sample app on this that you can check at https://blog.shajeelafzal.com/2017/12/13/firebase-realtime-database-pagination-guide-using-recyclerview/

    0 讨论(0)
  • 2020-11-28 09:22

    accepted answear dos not work when less then the max. itmes (21) in database. this is my solution build on the 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 a 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 load more 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 讨论(0)
  • 2020-11-28 09:27

    In the past (but no longer) a question regarding implementing Pagination to a query on Firestore was marked as a duplicate of this question I will answer for FireStore here.

    Paginate a query 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.

    0 讨论(0)
  • 2020-11-28 09:29

    You can achieve it by using Firebase database paging library as below code... In this code, I have shown Post as an data model item 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 below URL for reference https://firebaseopensource.com/projects/patilshreyas/firebaserecyclerpagination/app/readme.md/ Here you will find implementation of library which helps to implement Pagination of firebase data in RecyclerView

    I hope this will help you!

    0 讨论(0)
提交回复
热议问题