gpt4 book ai didi

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

转载 作者:搜寻专家 更新时间:2023-10-30 21:02:16 24 4
gpt4 key购买 nike

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

如果使用文档代码:

// 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:当用户滚动时,我需要使用回收站 View (不是 ListView )。谢谢

最佳答案

official documentation中有提到,解决这个问题的关键是使用startAfter()方法。因此,您可以通过将查询游标与 limit() 方法组合来对查询进行分页。您将能够使用批处理中的最后一个文档作为下一批处理的光标起点。

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

解决方案:

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

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

让我们先定义RecyclerView,将布局管理器设置为LinearLayoutManager 并创建一个列表。我们还使用空列表实例化适配器并将适配器设置为我们的 RecyclerView:

RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
List<ProductModel> list = new ArrayList<>();
ProductAdapter productAdapter = new ProductAdapter(list);
recyclerView.setAdapter(productAdapter);

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

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 布局只包含一个 View ,一个 TextView

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/text_view"
android:textSize="25sp"/>

holder 类应该是这样的:

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 query = 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()) {
for (DocumentSnapshot document : task.getResult()) {
ProductModel productModel = document.toObject(ProductModel.class);
list.add(productModel);
}
productAdapter.notifyDataSetChanged();
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 对象,表示查询中的最后一个可见项。在这种情况下,每第 15 个被声明为一个全局变量:

private DocumentSnapshot lastVisible;

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

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

如果你想实时获取数据,那么你需要使用 addSnapshotListener() 而不是使用 get() 调用,如关于 listening to multiple documents in a collection 的官方文档中所述.更多信息您可以找到以下文章:

关于java - 如何使用 Android 对 Firestore 进行分页?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50741958/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com