Firebase android分页
Posted
技术标签:
【中文标题】Firebase android分页【英文标题】:Firebase android pagination 【发布时间】: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 在我的应用程序中实现分页。 【参考方案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);
【讨论】:
我在让它反向工作时遇到问题,有什么想法吗? ***.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 实时数据库以上是关于Firebase android分页的主要内容,如果未能解决你的问题,请参考以下文章
Uncaught FirebaseError: Firebase: No Firebase App '[DEFAULT]' has been created - 在 vue.js 中调用 Fireba
Stripe 和 Firebase:FirebaseError:collection() 的第一个参数应为 CollectionReference、DocumentReference 或 Fireba