我阅读了Firestore文档和互联网上的所有文章(stackoverflow)关于Firestore分页但没有运气.我试图在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<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.
- Query next = db.collection("cities")
- .orderBy("population")
- .startAfter(lastVisible)
- .limit(25);
- // Use the query for pagination
- // ...
- }
- });
怎么做?文档没有太多细节.
PS:用户滚动时我需要使用回收站视图(不是列表视图).谢谢
解决方法
正如
official documentation中提到的,解决这个问题的关键是使用
startAfter()方法.因此,您可以通过将查询游标与limit()方法相结合来对查询进行分页.您将能够将批处理中的最后一个文档用作下一批的游标的开头.
要解决这个分页问题,请参阅我在post中的回答,其中我已逐步解释了如何从较小的块中加载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<ProductViewHolder> {
- private List<ProductModel> list;
- ProductAdapter(List<ProductModel> 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.
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/text_view"
- android:textSize="25sp"/>
这就是持有者类应该是这样的:
- 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<QuerySnapshot>() {
- @Override
- public void onComplete(@NonNull Task<QuerySnapshot> task) {
- if (task.isSuccessful()) {
- List<ProductModel> 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<QuerySnapshot>() {
- @Override
- public void onComplete(@NonNull Task<QuerySnapshot> 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);
- }
- }
- });
其中lastVisible是DocumentSnapshot对象,它表示查询中的最后一个visibile项.在这种情况下,每15个一个,它被声明为gloabl变量:
- private DocumentSnapshot lastVisible;
isScrolling和isLastItemReached也是全局变量,声明为:
- private boolean isScrolling = false;
- private boolean isLastItemReached = false;