Last active
November 30, 2021 10:26
-
-
Save greenrobot-team/4dbcd77fb8c77fce6499834bce8ec815 to your computer and use it in GitHub Desktop.
ObjectBox Android Paging 2 data source
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Collections; | |
import java.util.List; | |
import androidx.annotation.NonNull; | |
import androidx.paging.DataSource; | |
import androidx.paging.PositionalDataSource; | |
import io.objectbox.query.Query; | |
import io.objectbox.reactive.DataObserver; | |
/** | |
* A {@link PositionalDataSource} that loads entities based on an ObjectBox {@link Query} using | |
* offset and limit to implement paging support. The data source is invalidated if the query results | |
* change. | |
*/ | |
public class ObjectBoxDataSource<T> extends PositionalDataSource<T> { | |
private final Query<T> query; | |
@SuppressWarnings("FieldCanBeLocal") | |
private final DataObserver<List<T>> observer; | |
public static class Factory<Item> extends DataSource.Factory<Integer, Item> { | |
private final Query<Item> query; | |
public Factory(Query<Item> query) { | |
this.query = query; | |
} | |
@NonNull | |
@Override | |
public DataSource<Integer, Item> create() { | |
return new ObjectBoxDataSource<>(query); | |
} | |
} | |
public ObjectBoxDataSource(Query<T> query) { | |
this.query = query; | |
this.observer = data -> { | |
// if data changes invalidate this data source and create a new one | |
invalidate(); | |
}; | |
// observer will be automatically removed once GC'ed | |
query.subscribe().onlyChanges().weak().observer(observer); | |
} | |
@Override | |
public void loadInitial(@NonNull LoadInitialParams params, @NonNull LoadInitialCallback<T> callback) { | |
// note: limiting to int should be fine for Android apps | |
int totalCount = (int) query.count(); | |
if (totalCount == 0) { | |
callback.onResult(Collections.emptyList(), 0, 0); | |
return; | |
} | |
int position = computeInitialLoadPosition(params, totalCount); | |
int loadSize = computeInitialLoadSize(params, position, totalCount); | |
List<T> list = loadRange(position, loadSize); | |
if (list.size() == loadSize) { | |
callback.onResult(list, position, totalCount); | |
} else { | |
invalidate(); // size doesn't match request - DB modified between count and load | |
} | |
} | |
@Override | |
public void loadRange(@NonNull LoadRangeParams params, @NonNull LoadRangeCallback<T> callback) { | |
callback.onResult(loadRange(params.startPosition, params.loadSize)); | |
} | |
private List<T> loadRange(int startPosition, int loadCount) { | |
// note: find interprets loadCount 0 as no limit | |
return query.find(startPosition, loadCount); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment