I have two queries:
Query firstQuery = ref.orderBy(\"name\", Query.Direction.ASCENDING).limit(10);
getData(firstQuery);
Query secondQuery = ref.orderBy(\"pr
I ended up using a modified version of adapter class from the Friendly-eats code lab sample.
The following class allows you add an initial query and then set another one using the FirestoreAdapter.setQuery(query)
method.
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.OnLifecycleEvent
import androidx.recyclerview.widget.RecyclerView
import com.google.firebase.firestore.*
import com.google.firebase.firestore.EventListener
import java.util.*
/**
* RecyclerView adapter for displaying the results of a Firestore [Query].
*
* Note that this class forgoes some efficiency to gain simplicity. For example, the result of
* [DocumentSnapshot.toObject] is not cached so the same object may be deserialized
* many times as the user scrolls.
*
*
* See the adapter classes in FirebaseUI (https://github.com/firebase/FirebaseUI-Android/tree/master/firestore) for a
* more efficient implementation of a Firestore RecyclerView Adapter.
*/
abstract class FirestoreAdapter<VH : RecyclerView.ViewHolder>(private var query: Query,
private val lifecycleOwner: LifecycleOwner)
: RecyclerView.Adapter<VH>(), EventListener<QuerySnapshot>, LifecycleObserver {
private var listener: ListenerRegistration? = null
private val snapshots = ArrayList<DocumentSnapshot>()
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun startListening() {
if (listener == null) {
listener = query.addSnapshotListener(this)
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun stopListening() {
listener?.apply {
remove()
listener = null
}
snapshots.clear()
notifyDataSetChanged()
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
internal fun cleanup(source: LifecycleOwner) {
source.lifecycle.removeObserver(this)
}
override fun onEvent(snapshot: QuerySnapshot?, error: FirebaseFirestoreException?) {
when {
error != null -> onError(error)
else -> {
// Dispatch the event
snapshot?.apply {
for (change in documentChanges) {
when (change.type) {
DocumentChange.Type.ADDED -> onDocumentAdded(change)
DocumentChange.Type.MODIFIED -> onDocumentModified(change)
DocumentChange.Type.REMOVED -> onDocumentRemoved(change)
}
}
onDataChanged()
}
}
}
}
protected fun onDocumentAdded(change: DocumentChange) {
snapshots.add(change.newIndex, change.document)
notifyItemInserted(change.newIndex)
}
protected fun onDocumentModified(change: DocumentChange) {
if (change.oldIndex == change.newIndex) {
// Item changed but remained in same position
snapshots[change.oldIndex] = change.document
notifyItemChanged(change.oldIndex)
} else {
// Item changed and changed position
snapshots.removeAt(change.oldIndex)
snapshots.add(change.newIndex, change.document)
notifyItemMoved(change.oldIndex, change.newIndex)
}
}
protected fun onDocumentRemoved(change: DocumentChange) {
snapshots.removeAt(change.oldIndex)
notifyItemRemoved(change.oldIndex)
}
fun setQuery(query: Query) {
stopListening()
// Clear existing data
snapshots.clear()
notifyDataSetChanged()
// Listen to new query
this.query = query
startListening()
}
override fun getItemCount(): Int = snapshots.size
protected fun getSnapshot(index: Int): DocumentSnapshot = snapshots[index]
protected open fun onError(exception: FirebaseFirestoreException) {}
protected open fun onDataChanged() {}
}
There is nothing built-in to combine two queries in a FirestoreRecyclerAdapter
.
The best I can think of is creating a List
/array of the combined results in your app code and then using an array adapter. It's not ideal, since you won't be using FirebaseUI.
Alternatively, have a look at FirebaseUIs FirestorePagingAdapter, which combines multiples pages of (non-realtime) DocumentSnapshots
in a single recycler view.