web-dev-qa-db-fra.com

Firebase Android pagination

Je construis une application qui va montrer des vidéos stockées sur firebase. La liste des vidéos doit être paginée pour aller chercher les 20 dernières vidéos à la fois. 

 enter image description here

Voici le code que je pensais fonctionnerait 

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

    }

Mais le code ci-dessus récupère la liste complète des vidéos au lieu de vidéos limitées. Comment peut-on mettre en œuvre la pagination?.

15
Vihaan Verma

Vous trouverez ci-dessous le code que j'utilise pour la pagination, qui affiche en premier le dernier nœud.

      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);
        }
    }
15
Vihaan Verma

Vous souhaitez utiliser les méthodes limitToFirst/limitToLast pour extraire un nombre limité de résultats. 

videosQuery.orderByKey().limitToFirst(20)

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

Vous devriez vraiment envisager de changer la convention de nommage de vos vidéos pour inclure les 0 premiers (par exemple, vidéo01, vidéo02 ... vidéo10, vidéo11), car le code ci-dessus les affichera exactement tels que vous les avez décrits ci-dessus (ce qui, je suppose, est en panne?)

Si vous ajoutez les vidéos via Java, vous pouvez également laisser firebase créer les identifiants uniques via Push (). Les informations uniques sont générées de manière à pouvoir être classées de manière chronilogique, ce qui semble correspondre à votre besoin de saisir les vidéos les plus récentes (récemment ajoutées?).

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

4
crookful
 mPageEndOffset = 0;
 mPageLimit = 10;


 mPageEndOffset += mPageLimit;

 deviceListQuery = mDatabase.child("users")
 .orderByChild("id").limitToFirst(mPageLimit).startAt(mPageEndOffset);

 deviceListQuery.addValueEventListener(YourActivity.this);
4
Jayakrishnan PM

J'ai méthode suivante pour paginer à travers un nœud de base de données en temps réel firebase:

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

Chaque fois que j'atteins le bas des données paginées, j'appelle la fonction getUsers(mAdapter.getLastItemId());, puis le jeu d'enregistrements suivant s'affiche. 

J'ai écrit un guide complet avec un exemple d'application open source que vous pouvez consulter à l'adresse suivante: https://blog.shajeelafzal.com/2017/12/13/firebase-realtime-database-pagination-guide-using-recyclerview/

1
Shajeel Afzal

Puisque cette question concernant l’implémentation de Pagination dans une requête sur Firestore est marquée comme une copie de cette question, je vais y répondre ici. 

Paginer une requête sur 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);

            }
        });         
 }

Appelez maintenant la méthode loadCities() chaque fois que vous devez charger plus de villes.

1
lovish

La bibliothèque de pagination Android peut être utilisée pour implémenter la pagination des données extraites de la base de données Firebase. Les données sont affichées dans la vue du recycleur et le composant de pagination récupère les pages en réponse aux événements de défilement de l'utilisateur.

La source de données de pagination appelle votre objet DAO firebase en transmettant des paramètres de requête pour la page à afficher et les résultats sont renvoyés au composant de pagination à l’aide du rappel fourni.

Voici un exemple complet pour référence http://www.zoftino.com/firebase-pagination-using-Android-paging-library

0
Arnav Rao

Voici comment j'ai implémenté la pagination à partir de la base de données firebase. Considérons un cas si nous avons 100 messages. Donc, je charge d’abord les 20 derniers messages à partir de firebase, soit 81 à 100. Puis, lorsque je fais défiler la page vers le haut, j’appelle la fonction getMoreMessages() pour charger les 20 prochains messages (61 à 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
KishanSolanki124

les réponses acceptées ne fonctionnent pas si elles sont inférieures au max. itmes (21) in database ..__ Ceci est ma solution basée sur la réponse acceptée:

0) définir les 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) définir un auditeur:

       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) définir la charge plus auditeur:

        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) obtenir plus d'articles:

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

    }

s'amuser!!

0
Ronny Bigler