pushtorefresh / storio

Reactive API for SQLiteDatabase and ContentResolver.
Apache License 2.0
2.55k stars 182 forks source link

StorIO and pagination #799

Open Rainer-Lang opened 7 years ago

Rainer-Lang commented 7 years ago

Has anyone an example how to do pagination with StorIO?

nikitin-da commented 7 years ago

Hello, @Rainer-Lang ! You can apply offset and limit in query to specify rows you are interested in:

Query.builder()
        .table("tweets")
        .orderBy("date")
        .limit(30, 60) // offset and limit
        .build();

If you have some increasing primary key you can insure consistency if beginning of the list will change while pagination:

Query.builder()
        .table("tweets")
        .where("id < ?")
        .whereArgs(previousId)
        .orderBy("id DESC")
        .limit(30)
        .build();

Or you can just use get().cursor and cursor adapter=)

Rainer-Lang commented 7 years ago

@nikitin-da Thanks. And how about being notified about changes in the tables? Could this be a problem? I have a service which writes data in the background - and right now my view-data is always up-to-date.

nikitin-da commented 7 years ago

Changes doesn't contain which particular raws were affected, because we can't determinate it for example for raw queries. So I guess there is no pretty way to do this =(

This is one of possible solutions: observe table and query loaded pages using shared field - minLoadedId.

private Observable<Tweet> observeTweets() {
    return storio.observeChangesInTable("tables")
            .switchMap(changes -> storio.get().listOfObjects(Tweet.class)
                    .withQuery(
                            Query.builder()
                                    .table("tweets")
                                    .where("id > ?")
                                    .whereArgs(minLoadedId)
                                    .orderBy("id DESC")
                                    .build()
                    )
                    .prepare()
                    .asRxObservable());
}

private Single<Tweets> loadNextPage() {
    return storio.get()
            .listOfObjects(Tweet.class)
            .withQuery(
                    Query.builder()
                            .table("tweets")
                            .where("id > ?")
                            .whereArgs(minLoadedId)
                            .orderBy("id DESC")
                            .limit(30)
                            .build()
            )
            .prepare()
            .asRxSingle()
            .observeOn(AndroidScheduers.mainThread())
            .doOnSuccess(tweets -> minLoadedId = tweets.get(0).id());
}

So it allow fast initial load, but if user will load many pages - updates will be slow and all items will be in memory =(