如何使用Android对Firestore进行分页?

我阅读了Firestore文档以及关于Firestore分页的互联网(stackoverflow)上的所有文章,但没有运气。 我试图在docs中实现确切的代码,但没有任何反应。 我有一个基本的数据库项目(超过1250或更多),我想逐步得到它们。 通过滚动来加载15个项目(到数据库中的最后一项)。

如果使用docs代码:

// Construct query for first 25 cities, ordered by population Query first = db.collection("cities") .orderBy("population") .limit(25); first.get() .addOnSuccessListener(new OnSuccessListener() { @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. Query next = db.collection("cities") .orderBy("population") .startAfter(lastVisible) .limit(25); // Use the query for pagination // ... } }); 

怎么做? 文档没有太多细节。

PS:用户滚动时我需要使用回收站视图(不是列表视图)。 谢谢

正如官方文档中提到的,解决此问题的关键是使用startAfter()方法。 因此,您可以通过将查询游标与limit()方法相结合来对查询进行分页。 您将能够将批处理中的最后一个文档用作下一批的游标的开头。

要解决这个分页问题,​​请参阅我在这篇文章中的答案,我已逐步解释了如何从较小的块中加载Cloud Firestore数据库中的数据,并在按钮单击时将其显示在ListView

解:

要从Firestore数据库获取数据并在RecyclerView以较小的块显示,请按照以下步骤操作。

我们来看上面使用过产品的例子。 您可以使用产品,城市或任何您想要的东西。 原则是一样的。 假设您想在用户滚动时加载更多产品,我将使用RecyclerView.OnScrollListener

让我们首先定义RecyclerView并设置布局管理器:

 RecyclerView recyclerView = findViewById(R.id.recycler_view); recyclerView.setLayoutManager(new LinearLayoutManager(this)); 

假设我们有一个如下所示的数据库结构:

 Firestore-root | --- products (collection) | --- productId (document) | --- productName: "Product Name" 

一个看起来像这样的模型类:

 public class ProductModel { private String productName; public ProductModel() {} public ProductModel(String productName) {this.productName = productName;} public String getProductName() {return productName;} } 

这个适配器类应该如何:

 private class ProductAdapter extends RecyclerView.Adapter { private List list; ProductAdapter(List list) { this.list = list; } @NonNull @Override public ProductViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_product, parent, false); return new ProductViewHolder(view); } @Override public void onBindViewHolder(@NonNull ProductViewHolder productViewHolder, int position) { String productName = list.get(position).getProductName(); productViewHolder.setProductName(productName); } @Override public int getItemCount() { return list.size(); } } 

item_product布局仅包含一个视图,即TextView

  

这就是持有者类应该是这样的:

 private class ProductViewHolder extends RecyclerView.ViewHolder { private View view; ProductViewHolder(View itemView) { super(itemView); view = itemView; } void setProductName(String productName) { TextView textView = view.findViewById(R.id.text_view); textView.setText(productName); } } 

现在,让我们将限制定义为全局变量并将其设置为15

 private int limit = 15; 

现在让我们使用这个限制来定义查询:

 FirebaseFirestore rootRef = FirebaseFirestore.getInstance(); CollectionReference productsRef = rootRef.collection("products"); Query firstQuery = productsRef.orderBy("productName", Query.Direction.ASCENDING).limit(limit); 

以下是在您的案例中也具有魔力的代码:

 query.get().addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { List list = new ArrayList<>(); for (DocumentSnapshot document : task.getResult()) { ProductModel productModel = document.toObject(ProductModel.class); list.add(productModel); } ProductAdapter productAdapter = new ProductAdapter(list); recyclerView.setAdapter(productAdapter); lastVisible = task.getResult().getDocuments().get(task.getResult().size() - 1); RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { isScrolling = true; } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); LinearLayoutManager linearLayoutManager = ((LinearLayoutManager) recyclerView.getLayoutManager()); int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition(); int visibleItemCount = linearLayoutManager.getChildCount(); int totalItemCount = linearLayoutManager.getItemCount(); if (isScrolling && (firstVisibleItemPosition + visibleItemCount == totalItemCount) && !isLastItemReached) { isScrolling = false; Query nextQuery = productsRef.orderBy("productName", Query.Direction.ASCENDING).startAfter(lastVisible).limit(limit); nextQuery.get().addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task t) { if (t.isSuccessful()) { for (DocumentSnapshot d : t.getResult()) { ProductModel productModel = d.toObject(ProductModel.class); list.add(productModel); } productAdapter.notifyDataSetChanged(); lastVisible = t.getResult().getDocuments().get(t.getResult().size() - 1); if (t.getResult().size() < limit) { isLastItemReached = true; } } } }); } } }; recyclerView.addOnScrollListener(onScrollListener); } } }); 

其中lastVisibleDocumentSnapshot对象,它表示查询中的最后一个visibile项。 在这种情况下,每15个一个,它被声明为gloabl变量:

 private DocumentSnapshot lastVisible; 

isScrollingisLastItemReached也是全局变量,声明为:

 private boolean isScrolling = false; private boolean isLastItemReached = false; 

FirebaseUI-Android最近还推出了Firestore Paginator。

我已经在我的代码中使用它,并且它工作得很好 – 请记住,它使用.get()而不是.addSnapshotListener()进行操作,因此回收器不是实时的。

请参阅此处的文档:

https://github.com/firebase/FirebaseUI-Android/tree/master/firestore#using-the-firestorepagingadapter