【问题标题】:Firebase android paginationFirebase android分页
【发布时间】:2016-10-09 05:40:30
【问题描述】:

我正在构建一个应用程序,它将显示存储在 firebase 上的视频。视频列表需要分页,一次获取最近的 20 个视频。

这是我认为可行的代码

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

    }

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

【问题讨论】:

  • 你找到分页的地方了吗?
  • 你有什么分页的吗?我还需要使用 firebase 在我的应用程序中实现分页。

标签: android firebase android-recyclerview firebase-realtime-database


【解决方案1】:

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

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

【讨论】:

  • 你能告诉我 getMoreImages() 是你的覆盖方法吗???我也想使用你使用的分页概念。你的 onLoadMore 功能在哪里??
  • 片段在我的代码中实现了接口。您可以删除 @override 表示法
  • 您能解释一下.onNoMoreImages(); 是什么吗?谢谢
  • 感谢上面的代码,终于找到我需要的解决方案了!上面的childEvenListener 给了我重复的RecyclerView 项目,因为每次我查询时它们都没有被删除。所以我必须做的不同的是使用addListenerForSingleValueEvent 而不是childEventListener。这样监听器就会立即被移除。再次感谢!
  • 根据 Firebase 文档: 您可以使用 startAt()、endAt() 和 equalTo() 为查询选择任意起点、终点和等价点.这对于对数据进行分页或查找具有特定值的子项非常有用。
【解决方案2】:

我有以下方法通过 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/ 上查看

【讨论】:

    【解决方案3】:

    您希望使用 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。 uniqueid 是以按时间顺序排序的方式生成的,这听起来很适合您获取最新(添加的?)视频的需要。

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

    【讨论】:

    • 尝试使用 videosQuery.orderByKey().limitToLast(2);使用 ChildEventListener 仍然无法获得分页响应。
    • 这并不是真正的分页答案。它只限制对最后 x 部电影的一次响应。
    【解决方案4】:
     mPageEndOffset = 0;
     mPageLimit = 10;
    
    
     mPageEndOffset += mPageLimit;
    
     deviceListQuery = mDatabase.child("users")
     .orderByChild("id").limitToFirst(mPageLimit).startAt(mPageEndOffset);
    
     deviceListQuery.addValueEventListener(YourActivity.this);
    

    【讨论】:

    • 我在让它反向工作时遇到问题,有什么想法吗? stackoverflow.com/questions/40231335/…
    • 向数据添加一个具有递减值的字段,例如:unix_timestamp(或倒置时间戳)并在您的选择查询中使用limitToLast()。我们真的不需要分页,因为 firebase 查询执行和返回速度很快。我使用查询在单个查询中获取 1000 条记录到目前为止没有太多延迟
    • 如何附加 unix_timestamp(或倒置时间戳)?目前我正在通过以下方法添加时间戳 'ServerValue.TIMESTAMP'
    • @JayakrishnanPm 好吧,这不会迫使您在视频子实现中拥有一个 id 字段吗?并且 id 需要是一个整数,您必须自己在创建时递增?
    • @JacksOnF1re 如果你想按一个字段(整数字段)排序,然后添加一个时间戳字段,这样你就不需要以编程方式自动递增它。
    【解决方案5】:

    您可以通过使用 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 数据分页的库的实现

    希望对你有帮助!

    【讨论】:

    • 确保您显示的代码不是来自链接的复制/粘贴或抄袭
    • 这不完全是链接中的复制粘贴。因为在那个链接中,代码是以解释的形式给出的。
    【解决方案6】:

    这就是我从 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();
            }
        }
    

    【讨论】:

      【解决方案7】:

      Android 分页库可用于对从 firebase 数据库获取的数据进行分页。数据显示在回收器视图中,分页组件获取页面以响应用户滚动事件。

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

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

      【讨论】:

        【解决方案8】:

        接受的答案在小于最大值时不起作用。数据库中的项目(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);
        
            }
        

        玩得开心!

        【讨论】:

        • 嘿,你的答案很好,但你能告诉我如何在我的代码中添加它吗?
        【解决方案9】:

        如果你想从 firebase 实时数据库中获取列表并按分页降序,你需要像这样使用 smth:

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

        【讨论】:

          【解决方案10】:

          过去(但不再)a question 关于对 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() 方法即可。

          【讨论】:

          • 这个答案对于 firestore 数据库可能是正确的,但问题是在 firebase 数据库上。
          • 请回答 Firebase 实时数据库
          猜你喜欢
          • 1970-01-01
          • 2016-11-22
          • 2017-11-07
          • 2021-10-08
          • 1970-01-01
          • 2017-05-07
          • 1970-01-01
          • 2020-08-28
          • 1970-01-01
          相关资源
          最近更新 更多