有没有办法通过使用 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 个不同的查询(firstsecond)传递给单个适配器,这是不可能的与FirestoreRecyclerAdapter。您可以将第一个查询或第二个查询与适配器的单个实例一起使用。

一种解决方案是创建两个不同的列表,其中包含每个查询的结果并将它们组合起来。然后您可以将结果列表传递给另一个适配器,比如说ArrayAdapter,然后将结果显示到ListView 中,甚至更好地显示在RecyclerView 中。这种情况下的问题是您将无法使用FirestoreRecyclerAdapter 类提供的实时功能,但这种方法将解决您的问题。

编辑:

根据您在评论部分的要求,我将举例说明如何使用ListViewArrayAdapter 以最简单的方式对单击按钮的查询进行分页。向下滚动时,您也可以使用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) 多次运行

有没有办法通过自定义缓动方程使用 UIView 动画

用户有没有办法使用 iPhone sdk 通过 LinkedIn 邀请他们的朋友?

有没有办法通过使用自动完成来缓存和显示搜索列表

有没有办法在 MacOS 上通过终端使用普通键盘文本选择?

有没有办法通过使用 FirestoreRecyclerAdapter 组合查询游标来对查询进行分页?