Cómo paginar Firestre con Android?

Leí la documentación de Firestre y todos los artículos en Internet (stackoverflow) sobre la paginación de Firestre, pero no tuve suerte. Traté de implementar el código exacto en documentos, pero no pasa nada. Tengo una base de datos básica con elementos (más de 1250 o más) y quiero obtenerlos progresivamente. Al desplazarse para cargar 15 elementos (hasta el último elemento de la base de datos).

Si usa el código de documentación:

// 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 // ... } }); 

¿Cómo hacer? La documentación no tiene demasiados detalles.

PD: lo necesito con la vista de reciclador (no con la vista de lista) cuando el usuario se desplaza. Gracias

Como se menciona en la documentación oficial , la clave para resolver este problema es utilizar el método startAfter () . De modo que puede paginar consultas combinando cursores de consulta con el método de limit() . Podrá utilizar el último documento en un lote como inicio de un cursor para el siguiente lote.

Para resolver este problema de paginación, consulte mi respuesta de esta publicación , en la que he explicado paso a paso, cómo puede cargar datos de una base de datos de Cloud Firestre en trozos más pequeños y visualizarlos en un clic de ListView en el botón.

Solución:

Para obtener los datos de su base de datos de Firestre y mostrarlos en trozos más pequeños en un RecyclerView , siga los pasos a continuación.

Tomemos el ejemplo anterior en el que he usado productos. Puedes usar productos, ciudades o lo que quieras. Los principios son lo mismo. Suponiendo que desea cargar más productos cuando el usuario se desplaza, RecyclerView.OnScrollListener .

Definamos primero RecyclerView y configuremos el administrador de diseño:

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

Supongamos que tenemos una estructura de base de datos que se ve así:

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

Y una clase modelo que se ve así:

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

Esta es la forma en que debería verse la clase de adaptador:

 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(); } } 

El diseño item_product contiene solo una vista, una TextView .

  

Y así es como debería lucir la clase de titular:

 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); } } 

Ahora, definamos un límite como variable global y establézcalo en 15 .

 private int limit = 15; 

Definamos ahora la consulta que usa este límite:

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

Aquí está el código que también hace la magia en su caso:

 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); } } }); 

En el cual lastVisible es un objeto DocumentSnapshot que representa el último elemento visual de la consulta. En este caso, cada 15'th y se declara como variable gloabl:

 private DocumentSnapshot lastVisible; 

Y isScrolling y isLastItemReached también son variables globales y se declaran como:

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

FirebaseUI-Android también salió recientemente con Firestre Paginator.

Lo he usado en mi código, y funciona muy bien, solo tenga en cuenta que opera usando .get () en lugar de .addSnapshotListener (), por lo que el reciclador no está en tiempo real.

Vea los documentos aquí:

https://github.com/firebase/FirebaseUI-Android/tree/master/firestre#using-the-firestrepagingadapter