Skip to content
This repository has been archived by the owner on Aug 17, 2020. It is now read-only.

Any way to reload the database and make all observables to re-query? #39

Open
varyoo opened this issue Aug 13, 2015 · 4 comments
Open
Labels

Comments

@varyoo
Copy link

varyoo commented Aug 13, 2015

Reload SQLiteOpenHelper and re-query

In my app I have a import/export functionality, by importing, the SQLite database file is replaced by one on the sdcard, so I need to reload the SQLiteOpenHelper and then notify all the Queries.

Something like the following method would be really handy!

public void reloadDatabase(SQLiteOpenHelper helper, Set<String> tables){
   // Replace the SQLiteOpenHelper
   synchronized (databaseLock) {
      readableDatabase = null;
      writeableDatabase = null;
      this.helper.close();
      this.helper = helper;
   }
   // Make all Queries to reload
   sendTableTrigger(tables);
}

Or prehaps BriteDatabase can save a Set of tables, filled as we query them, to be notified on a potential database reload?

I guess I could make the user restart the app, but I rather not.

SQLBrite is amazing as it is very simple and allow us to get rid of loaders, and IMO notifying on tables is far better than the Uri system, thanks for creating SQLBrite!

Re-query only

Let's say my app is a calendar, I have an upcoming event list, starting by today's events.
In every event list I want to mark each yesterday's event as missed.

Then I need to reload event's Queries every day at 00:00.
In this particular case it would make sense to make the sendTableTrigger() public and call it every day.

I could also use a Observable.combineLatest with a Query and a PublishSubject and call this Subject every day to run the Query again, but since table triggers are managed the same way, it seems simple to switch sendTableTrigger() to public.

To support this idea; ContentResolver's notifyChange(Uri uri, null) is public.

@xMikeTx
Copy link

xMikeTx commented Aug 17, 2015

I needed the same thing, so I just exposed the triggers.

public PublishSubject<Set<String>> getTriggersSubject() {
     return triggers;
}

Would be great if this would be integrated in the main branch.
But I am not sure, whether this is is the smartest solution.

xMikeTx@baffb9c

@JakeWharton
Copy link
Collaborator

As to the re-query case, you can run a query more than once so you can use something like combineLatest with another stream that emits a new dummy value every day at midnight.

Observable.combineLatest(queryObservable, midnightObservable, (q, m) -> q)
   .subscribe(query -> /* .. */);

In this instance midnightObservable could be a PublishSubject that sent out an item when an AlarmManager fires.

I'm not super sure about how widespread the use of reloading helpers is. One solution would just be to replace your BriteDatabase with an Observable<BriteDatabase> and switchMap to create the query observable.

Observable<BriteDatabase> dbObservable = /* .. */
dbObservable.switchMap(db -> db.createQuery("SELECT * FROM table", "table"))
    .subscribe(query -> /* .. */);

@varyoo
Copy link
Author

varyoo commented Aug 22, 2015

By using Observable<BriteDatabase> instead of a BriteDatabase I ended up duplicating createQuery:

Observable<Query> createQuery(Iterable<String> tables, String sql, String... args){
   return dbObservable.switchMap(db -> db.createQuery(tables, sql, args);
}

Which is a fine solution, thank you.

Another idea is to provide an Observable<SQLiteOpenHelper> instead of the single SQLiteOpenHelper reference in SqlBrite.wrapDatabaseHelper, and put the switchMap logic inside BriteDatabase to avoid using it externally.
And SqlBrite.wrapDatabaseHelper(Observable<helper>) could even coexist with the original SqlBrite.wrapDatabaseHelper(helper).

About the re-query, I keep thinking making sendTableTrigger public is better than rewriting a PublishSubject to trigger a reload, but anyway you're the boss.

If you feel the issue is closed, then it's closed for me too.
Thank you!

@JakeWharton
Copy link
Collaborator

It's actually not that easy to accept an Observable<SQLiteOpenHelper> in SqlBrite because of the synchronous APIs that it offers. I'll have to think about it more to see if there's anything we can do.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants