Firebase Android 分页功能

21
我正在开发一个应用程序,它将显示存储在Firebase上的视频。视频列表需要进行分页,每次获取最近的20个视频。
enter image description here
这里是我认为会起作用的代码。
  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);

    }

但是上面的代码检索到整个视频列表,而不是有限制的视频。如何实现分页。


您找到了分页的方法吗? - Raghunandan
3
你有没有考虑过分页?我也需要在我的应用程序中使用 Firebase 实现分页。 - Arpit Patel
10个回答

18

以下是我用于分页的代码,它会先显示最新的节点。

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

代码中的片段实现了接口。您可以删除@override注释。 - Vihaan Verma
你能解释一下 .onNoMoreImages(); 是什么吗?谢谢。 - Drew Szurko
2
根据Firebase文档:您可以使用startAt()、endAt()和equalTo()来选择查询的任意起始点、结束点和等价点。这对于分页数据或查找具有特定值子项的项目非常有用。 - mirzak
我不明白,如果你有19呢?你永远不会渲染任何东西吗? - desgraci
我从你的回答中理解了逻辑,但请用简单的步骤并简化它。 - Adnan Bashir
显示剩余3条评论

14

我有以下方法来对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;
            }
        });
    }
每当我到达分页数据的底部时,我会调用getUsers(mAdapter.getLastItemId());,然后它会带来下一组记录。
我编写了一个完整的指南,并提供了开源示例应用程序,您可以在https://blog.shajeelafzal.com/2017/12/13/firebase-realtime-database-pagination-guide-using-recyclerview/上查看。

firebaser here 很好的回答。现在,我会使用 startAfter 而不是 startAt,以防止分页之间出现重复项。 - Frank van Puffelen

4
你需要使用limitToFirst/limitToLast方法来获取有限数量的结果。
videosQuery.orderByKey().limitToFirst(20)

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

你应该考虑更改视频的命名规则,包括前导0(例如video01,video02... video10,video11),因为上面的代码将按照你现有的方式显示它们(我假设是无序的?)。
或者,如果你是通过Java添加视频,你可以让Firebase通过push()创建唯一的id。这些唯一的id是按时间顺序生成的,听起来适合你获取最新添加的视频的需求。

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


尝试使用videosQuery.orderByKey().limitToLast(2);与ChildEventListener,仍无法获得分页响应。 - Vihaan Verma
1
这并不是关于分页的答案。它只是将一次性响应限制为最后 x 部电影。 - alltooconfusingthereforesleep

4
 mPageEndOffset = 0;
 mPageLimit = 10;


 mPageEndOffset += mPageLimit;

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

 deviceListQuery.addValueEventListener(YourActivity.this);

1
我在反向获取数据方面遇到了问题,有什么想法吗?http://stackoverflow.com/questions/40231335/how-to-paginate-firebase-from-the-last-items-to-the-first - Lion789
向数据添加一个具有降序值的字段,例如:unix_timestamp(或反转时间戳),并在选择查询中使用limitToLast()。我们不需要分页,因为Firebase查询执行和返回速度快。我使用查询一次获取1000条记录,在单个查询中没有遇到太多延迟。 - Jayakrishnan
如何附加Unix时间戳(或反转时间戳)?目前我是通过以下方法添加时间戳的:'ServerValue.TIMESTAMP' - Zen
@JayakrishnanPm 嗯,这不会强制你在视频子实现中拥有一个id字段吗?而且id需要是一个整数,你必须自己在创建时递增它吗? - JacksOnF1re
@JacksOnF1re 如果你想按一个字段(整数字段)排序,那么添加一个时间戳字段,这样你就不需要在程序中自动递增它。 - Jayakrishnan
@JayakrishnanPM java.lang.IllegalArgumentException: 必须在使用orderByKey()时与startAt(String value)、endAt(String value)或equalTo(String value)结合使用。不支持其他类型的值或使用带有2个参数的版本。 - Mohamed Zakaria El-Zoghbi

1
你可以使用Firebase数据库分页库来实现,如下所示的代码... 在这段代码中,我展示了Post作为数据模型项和PostViewHolder作为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);

只需访问以下URL以供参考https://firebaseopensource.com/projects/patilshreyas/firebaserecyclerpagination/app/readme.md/,在此处您将找到库的实现,该库有助于在RecyclerView中实现Firebase数据的分页。

我希望这可以帮助您!


请确保您展示的代码不是从链接中复制/粘贴的,这是抄袭。 - Jean-François Fabre
这并不是从链接中复制粘贴的。因为在那个链接中,代码是以解释格式给出的。 - Shreyas Patil

0

Android分页库可用于实现从Firebase数据库获取的数据的分页。数据在回收视图中显示,分页组件响应用户滚动事件来获取页面。

分页数据源调用您的Firebase DAO对象,传递查询参数以显示页面,并使用提供给它的回调将结果传递回分页组件。

这里有一个完整的示例供参考 http://www.zoftino.com/firebase-pagination-using-android-paging-library


0
这是我如何从Firebase数据库实现分页的方法。考虑一个情况,如果我们有100条消息。所以我首先从Firebase加载最后20条消息,即81到100。然后在向上滚动时,我调用getMoreMessages()函数来加载下一批20条消息,即61到80等等。
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

当数据库中的项目数少于最大项目数(21)时,接受的答案无法正常工作。

这是我基于接受的答案构建的解决方案:

0)设置变量

        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) 设置监听器:

       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) 设置加载更多监听器:

        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) 获取更多的项目:

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

    }

玩得开心!


你的回答很好,但您能告诉我如何将它与我的代码结合起来吗? - Geetika Sachdeva

0
如果你想要从Firebase实时数据库获取降序分页列表,你需要使用类似以下的代码:
Query query = myRef.child("stories").orderByChild("takenAt").endAt(1600957136000L).limitToLast(30);

完整代码,两个请求

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

-1
过去(但现在不再)有关在Firestore上实现分页查询的问题被标记为此问题的重复,我将在此回答有关FireStore的问题。 在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);

            }
        });         
 }

现在只需在需要加载更多城市时调用loadCities()方法即可。

2
这个答案可能适用于Firestore数据库,但问题是关于Firebase数据库的。 - Ashish Yadav
请回答Firebase实时数据库相关问题。 - Mahi Tej Gvp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接