有没有办法通过使用 FirestoreRecyclerAdapter 组合查询游标来对查询进行分页?
Posted
技术标签:
【中文标题】有没有办法通过使用 FirestoreRecyclerAdapter 组合查询游标来对查询进行分页?【英文标题】:Is there a way to paginate queries by combining query cursors using FirestoreRecyclerAdapter? 【发布时间】:2018-11-08 13:54:25 【问题描述】:我的查询如下所示:
Query first = ref.orderBy("name", Query.Direction.ASCENDING).limit(10);
这就是我将数据显示到我的RecyclerView
的方式。
firestoreRecyclerOptions = new FirestoreRecyclerOptions.Builder<ModelClass>().setQuery(query, ModelClass.class).build();
myFirestoreRecyclerAdapter = new MyFirestoreRecyclerAdapter(firestoreRecyclerOptions);
recyclerView.setAdapter(myFirestoreRecyclerAdapter);
我正在尝试使用here 中指定的分页,但无法解决。
first.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>()
@Override
public void onSuccess(QuerySnapshot documentSnapshots)
DocumentSnapshot lastVisible = documentSnapshots.getDocuments().get(documentSnapshots.size() - 1);
Query second = ref.orderBy("name", Query.Direction.ASCENDING).startAfter(lastVisible).limit(10);
//Create a firestoreRecyclerOptions and setting the adapter
);
有没有办法通过使用FirestoreRecyclerAdapter
组合查询游标来对查询进行分页?这甚至可能吗?
【问题讨论】:
***.com/questions/43289731/… @Eminem 感谢您的评论。这也适用于 Cloud Firestore 吗?在那个例子中,我看不到FirebaseRecyclerAdapter
的用法,这几乎是一样的。
***.com/questions/46795445/…
@Eminem 我研究了上一篇文章并没有帮助我。你还有别的想法吗?谢谢!
@Eminem 你能仔细看看我的问题吗?谢谢
【参考方案1】:
正如@FrankvanPuffelen 已经在您之前的@987654321@ 中回答的那样,您无法做到这一点,因为在您的情况下,您应该将 2 个不同的查询(first
和 second
)传递给单个适配器,这是不可能的与FirestoreRecyclerAdapter
。您可以将第一个查询或第二个查询与适配器的单个实例一起使用。
一种解决方案是创建两个不同的列表,其中包含每个查询的结果并将它们组合起来。然后您可以将结果列表传递给另一个适配器,比如说ArrayAdapter
,然后将结果显示到ListView
中,甚至更好地显示在RecyclerView
中。这种情况下的问题是您将无法使用FirestoreRecyclerAdapter
类提供的实时功能,但这种方法将解决您的问题。
编辑:
根据您在评论部分的要求,我将举例说明如何使用ListView
和ArrayAdapter
以最简单的方式对单击按钮的查询进行分页。向下滚动时,您也可以使用RecyclerView
来实现相同的目的。但是为了简单起见,假设我们有一个ListView
和一个Button
,并且我们希望在每次单击按钮时将更多项目加载到列表中。为此,让我们首先定义视图:
ListView listView = findViewById(R.id.list_view);
Button button = findViewById(R.id.button);
假设我们有一个如下所示的数据库结构:
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;
@Override
public String toString() return productName;
现在,让我们定义一个查询,并将限制设置为3
。
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference productsRef = rootRef.collection("products");
Query firstQuery = productsRef.orderBy("productName", Query.Direction.ASCENDING).limit(3);
这意味着每次单击按钮时,我们都会再加载 3 个项目。现在,这里是神奇的代码:
firstQuery.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);
ArrayAdapter<ProductModel> arrayAdapter = new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, list);
listView.setAdapter(arrayAdapter);
lastVisible = task.getResult().getDocuments().get(task.getResult().size() - 1);
button.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
Query nextQuery = productsRef.orderBy("productName", Query.Direction.ASCENDING).startAfter(lastVisible).limit(3);
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);
arrayAdapter.notifyDataSetChanged();
lastVisible = t.getResult().getDocuments().get(t.getResult().size() - 1);
);
);
);
其中lastVisible
是一个DocumentSnapshot
对象,表示查询中的最后一个可见项。在这种情况下,每三分之一,它被声明为 gloabl 变量:
private DocumentSnapshot lastVisible;
编辑2:
Here 您还可以解决如何从 Firestore 数据库中获取数据并在用户滚动时将其以较小的块显示在 RecyclerView
中。
【讨论】:
你是说我无法使用FirestoreRecyclerAdapter
?
不,按照您尝试的方式。您应该考虑使用其他方法。
这基本上是另一个问题,但是好的,为了更好地理解,我会写几行代码。
请查看我的更新答案并告诉我它是否有效。
对不起,我忘了提。是的,它被声明为全局变量。请再次查看我的更新答案。【参考方案2】:
一种可能的方法是将每个项目的按键保存在单独的节点中。
然后从该节点获取所有键到数组列表或其他东西..
然后根据你的分页号从这个数组 List 中获取键,并使用 orderByKey 查询和 startAt 和 LimitToFirst 查询组合来制作分页算法
【讨论】:
嗨,保罗,感谢您的回答。我没有使用按键,我使用的是新的 Cloud Firestore 数据库。这里没有按键。您的想法在使用 Firebase 实时数据库时应该可行,但有什么方法可以使用FirestoreRecyclerAdapter
实现这一点?
我不知道这是否正确将变量 second 更改为简单地 first 然后在任何按钮按下或执行 first.get().addOnSuccessListener 行时,可能会这样工作
请给我一个具体的例子。我没听懂你的意思。
请添加您当前实现的源代码,问题似乎不完整
我从头开始添加代码。这是一个简单的例子。以上是关于有没有办法通过使用 FirestoreRecyclerAdapter 组合查询游标来对查询进行分页?的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法使用预编译的 sql 完成工作并通过 java api (bigquery) 多次运行