-
Notifications
You must be signed in to change notification settings - Fork 132
Listening for data changes
SquidDatabase allows users to listen for changes to tables using DataChangedNotifier objects. DataChangedNotifier instances are constructed with a list of tables they are interested in listening to (or an empty list to listen to all tables):
// For listening to the people table
DataChangedNotifier<T> personNotifier = new DataChangedNotifier<T>(Person.TABLE) {
...
}
// For listening to all tables
DataChangedNotifier<T> globalNotifier = new DataChangedNotifier<T>() {
...
}
The general principle of DataChangedNotifier is to accumulate objects representing the notifications to be sent during a transaction, and then send them all on successful transaction completion. It is an abstract class, so users are free to override it and implement data changed notifications in whatever way they see fit. However, SquiDB provides a few built-in implementations of DataChangedNotifier to cover some common use cases.
UriNotifier can help you listen for and respond to database changes using the standard Android ContentObserver mechanism. When you create an instance of UriNotifier, you will have to override the accumulateNotificationObjects
method. In this case, the objects to be accumulated are the Uris to be notified. Using information provided by the SquidDatabase about what kind of write occurred, you can construct a Uri and add that Uri to the accumulator set:
UriNotifier peopleNotifier = new UriNotifier(Person.TABLE) {
@Override
protected abstract boolean accumulateNotificationObjects(Set<Uri> accumulatorSet,
SqlTable<?> table, SquidDatabase database, DBOperation operation,
AbstractModel modelValues, long rowId) {
// Notifies some constant Uri for any update on the people table
accumulatorSet.add(Person.CONTENT_URI);
}
}
Any Uri you add to the accumulatorSet
set will get a notification once the currently running transaction has completed successfully.
Note: Uris like Person.CONTENT_URI
will not be generated automatically, but if you declare them (or anything else) as public static final fields in your model spec classes they'll be copied to the generated model.
Generally, you'll probably want to listen for changes using an instance of SquidCursorLoader, so that your cursors will automatically be reloaded. This is pretty easy too--when constructing your SquidCursorLoader, just call setNotificationUri
:
SquidCursorLoader<Student> loader = new SquidCursorLoader(context, database, Person.class,
Query.select(Person.PROPERTIES));
loader.setNotificationUri(Person.CONTENT_URI);
Of course, you can also manually call [ContentResolver.registerContentObserver](http://developer.android.com/reference/android/content/ContentResolver.html#registerContentObserver(android.net.Uri,%20boolean,%20android.database.ContentObserver) to register your own ContentObservers on Uris as well.
SimpleDataChangedNotifier allows you to run arbitrary code on successful transaction completion. It doesn't care what changes occurred, only that some write occurred on the table(s) it listens to:
final AtomicInteger callCount = new AtomicInteger(0);
SimpleDataChangedNotifier simpleNotifier = new SimpleDataChangedNotifier(Person.TABLE) {
@Override
protected void onDataChanged() {
callCount.incrementAndGet();
}
}
In this example, callCount
will be incremented once for every transaction that writes to the people table.
This is pretty easy--just call registerDataChangedNotifier
on your SquidDatabase instance. Generally, you'll probably want to register these at instantiation time, since we highly recommend that your database objects be singletons:
MyDatabase database = new MyDatabase(context);
database.registerUriNotifier(peopleNotifier);
See also: