Skip to content

Instantly share code, notes, and snippets.

@greenrobot-team
Last active November 30, 2021 10:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save greenrobot-team/4dbcd77fb8c77fce6499834bce8ec815 to your computer and use it in GitHub Desktop.
Save greenrobot-team/4dbcd77fb8c77fce6499834bce8ec815 to your computer and use it in GitHub Desktop.
ObjectBox Android Paging 2 data source
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