From d2456c541dfe7129cc506424c3f7ec0f49901065 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iago=20Louren=C3=A7o?= Date: Sun, 14 Jul 2024 14:05:55 -0300 Subject: [PATCH] fix(DatabasePagingSource): Refactor the class to deal with orderbyChild queries I've implemented the solution provided in #2000 originally in Kotlin. Co-Authored-By: Dario Elyasy <5619462+beyondeye@users.noreply.github.com> --- .../paging/DatabasePagingOptions.java | 2 +- .../database/paging/DatabasePagingSource.java | 70 ++++++++++++++++--- 2 files changed, 63 insertions(+), 9 deletions(-) diff --git a/database/src/main/java/com/firebase/ui/database/paging/DatabasePagingOptions.java b/database/src/main/java/com/firebase/ui/database/paging/DatabasePagingOptions.java index 012de7bcb..139645038 100644 --- a/database/src/main/java/com/firebase/ui/database/paging/DatabasePagingOptions.java +++ b/database/src/main/java/com/firebase/ui/database/paging/DatabasePagingOptions.java @@ -94,7 +94,7 @@ public Builder setQuery(@NonNull Query query, public Builder setQuery(@NonNull Query query, @NonNull PagingConfig config, @NotNull SnapshotParser parser) { - final Pager pager = new Pager<>(config, + final Pager pager = new Pager<>(config, () -> new DatabasePagingSource(query)); mData = PagingLiveData.cachedIn(PagingLiveData.getLiveData(pager), mOwner.getLifecycle()); diff --git a/database/src/main/java/com/firebase/ui/database/paging/DatabasePagingSource.java b/database/src/main/java/com/firebase/ui/database/paging/DatabasePagingSource.java index 0544a7cfe..605fef312 100644 --- a/database/src/main/java/com/firebase/ui/database/paging/DatabasePagingSource.java +++ b/database/src/main/java/com/firebase/ui/database/paging/DatabasePagingSource.java @@ -1,12 +1,14 @@ package com.firebase.ui.database.paging; import android.annotation.SuppressLint; +import android.util.Pair; import com.google.android.gms.tasks.Task; import com.google.android.gms.tasks.Tasks; import com.google.firebase.database.DataSnapshot; import com.google.firebase.database.DatabaseError; import com.google.firebase.database.Query; +import com.google.firebase.database.snapshot.Index; import org.jetbrains.annotations.Nullable; @@ -21,7 +23,7 @@ import io.reactivex.rxjava3.core.Single; import io.reactivex.rxjava3.schedulers.Schedulers; -public class DatabasePagingSource extends RxPagingSource { +public class DatabasePagingSource extends RxPagingSource { private final Query mQuery; private static final String STATUS_DATABASE_NOT_FOUND = "DATA_NOT_FOUND"; @@ -32,18 +34,45 @@ public DatabasePagingSource(Query query) { this.mQuery = query; } + public Query startAt_childvalue(Object startvalue, String keyvalue) { + if (startvalue instanceof String) + return mQuery.startAt((String) startvalue, keyvalue); + else if (startvalue instanceof Boolean) + return mQuery.startAt((Boolean) startvalue, keyvalue); + else if (startvalue instanceof Double) + return mQuery.startAt((Double) startvalue, keyvalue); + else if (startvalue instanceof Long) + return mQuery.startAt(((Long) startvalue).doubleValue(), keyvalue); + else + return mQuery; + } + /** * DatabaseError.fromStatus() is not meant to be public. */ @SuppressLint("RestrictedApi") @NonNull @Override - public Single> loadSingle(@NonNull LoadParams params) { + public Single> loadSingle(@NonNull LoadParams params) { Task task; + + Index queryChildPathIndex = mQuery.getSpec().getIndex(); + Pair pKey = (Pair) params.getKey(); + if (params.getKey() == null) { task = mQuery.limitToFirst(params.getLoadSize()).get(); } else { - task = mQuery.startAt(null, params.getKey()).limitToFirst(params.getLoadSize() + 1).get(); + //change mQuery.startAt at value if child index + //if not null then what we have here is orderByChild query + if (queryChildPathIndex != null) {//orderByChild query mode + task = startAt_childvalue(pKey.first, pKey.second) + .limitToFirst(params.getLoadSize() + 1) + .get(); + } else { + task = mQuery.startAt(null, pKey.second) + .limitToFirst(params.getLoadSize() + 1) + .get(); + } } return Single.fromCallable(() -> { @@ -54,7 +83,7 @@ public Single> loadSingle(@NonNull LoadParams data = new ArrayList<>(); - String lastKey = null; + Pair lastKey = null; if (params.getKey() == null) { for (DataSnapshot snapshot : dataSnapshot.getChildren()) { @@ -77,7 +106,14 @@ public Single> loadSingle(@NonNull LoadParams(lastkey_c, "") : new Pair<>( + lastkey_c, + lastkey_k); + } return toLoadResult(data, lastKey); } else { @@ -99,9 +135,9 @@ public Single> loadSingle(@NonNull LoadParams toLoadResult( + private LoadResult toLoadResult( @NonNull List snapshots, - String nextPage + Pair nextPage ) { return new LoadResult.Page<>( snapshots, @@ -111,6 +147,24 @@ private LoadResult toLoadResult( LoadResult.Page.COUNT_UNDEFINED); } + @SuppressLint("RestrictedApi") + private Object getLastPageChildKey(@NonNull List data, Index index) { + if (index == null) return null; + if (data.isEmpty()) { + return null; + } else { + return getChildValue(data.get(data.size() - 1), index); + } + } + + @SuppressLint("RestrictedApi") + private Object getChildValue(DataSnapshot snapshot, Index index) { + String keypath = index.getQueryDefinition(); + DataSnapshot data = snapshot.child(keypath); + if (!data.exists()) return null; + return data.getValue(); + } + @Nullable private String getLastPageKey(@NonNull List data) { if (data.isEmpty()) { @@ -122,7 +176,7 @@ private String getLastPageKey(@NonNull List data) { @Nullable @Override - public String getRefreshKey(@NonNull PagingState state) { + public String getRefreshKey(@NonNull PagingState state) { return null; } }