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

Changes in SquiDB 2.0

Sam Bosley edited this page Sep 17, 2015 · 4 revisions

SquiDB 2.0 API changes

The SquiDB API changed in a few small but significant ways in version 2.0 This document outlines the changes as well as some examples of how to update your code for the new APIs.

DatabaseDao and AbstractDatabase replaced by unified SquidDatabase

This is the biggest API change in SquiDB 2.0. The DatabaseDao class is gone, so any code that references an instance of it will need to be updated. We don't make this change lightly, but feel that it's in the best interest of the API moving forward. Here are some of the reasons behind this change:

  • The fact that DatabaseDao wrapped an AbstractDatabase subclass made it hard to know what kind of database you were talking to, especially in apps with multiple databases. Now, all that's required is to subclass SquidDatabase instead of AbstractDatabase, and you can talk directly to your SquidDatabase subclass for all database I/O, which means you always know what kind of database you're talking to.
  • You can now define whatever custom helper/utility methods you want directly in your database class (using any of the available database/dao methods) without also needing to create a subclass of DatabaseDao.
  • Dao-style methods that work with model objects are now easily available from hooks like onUpgrade() and onTablesCreated().

SquidDatabase includes all the same methods DatabaseDao used to (with the exception of some changes to UriNotifiers; see below), so you can call the same methods on it directly wherever you are currently calling DatabaseDao. This may be a big change, but it's a conceptually simple one when it comes to updating your code.

Relevant API changes:

  • Where you used to create a singleton instance of DatabaseDao wrapping a singleton instance of your AbstractDatabase subclass, now create just a singleton instance of your SquidDatabase subclass instead.
  • E.g. If you are using dependency injection to get an instance of DatabaseDao, @Inject DatabaseDao dao becomes @Inject MyDatabase db
  • AbstractDatabase.getName, a protected abstract method, is now a public abstract method in SquidDatabase
  • Occurrences of SQLiteDatabase in hooks like onUpgrade have been replaced with SQLiteDatabaseWrapper. The interfaces are identical so no method calls will need to change, but the method signatures themselves will need to be updated. This is to support connecting to custom SQLite builds (see below)

These:

public class MyDatabase extends AbstractDatabase {
    @Override
    protected String getName() {
        return "myDb.db"
    }

    @Override
    protected boolean onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Do upgrade
        return true;
    }
    // Other overridden methods
}
// Singleton dao
DatabaseDao dao = new DatabaseDao(new MyDatabase(context));

Become these:

public class MyDatabase extends SquidDatabase {
    @Override
    public String getName() {
        return "myDb.db"
    }

    @Override
    protected boolean onUpgrade(SQLiteDatabaseWrapper db, int oldVersion, int newVersion) {
        // Do upgrade
        return true;
    }
    // Other overridden methods
}
// Singleton database
MyDatabase database = new MyDatabase(context);

Fully generic data change notification mechanism

DatabaseDao used to allow you to register UriNotifier objects to listen to tables and send notifications to Uris via the Android ContentResolver when table writes occurred. This mechanism still exists, but it is now part of a more generic notification mechanism.

ReactiveSquidDatabase

An add-on module has been added for those who wish to listen for data changes using RxJava Observables. Users can add squidb-reactive as a dependency to gain access to ReactiveSquidDatabase, an extension of SquidDatabase that adds apis for working with RxJava. See the ReactiveSquidDatabase Javadocs for more information.

Relevant API changes:

  • UriNotifier now subclasses the generic class DataChangedNotifier. UriNotifier's abstract method addUrisToNotify has been replaced by DataChangedNotifier's abstract method accumulateNotificationObjects:

This:

new UriNotifier(Task.TABLE, Tag.TABLE) {
    @Override
    public void addUrisToNotify(Set<Uri> uris, SqlTable<?> table,
            String databaseName, DBOperation operation,
            AbstractModel modelValues, long rowId) {
        uris.add(Task.CONTENT_URI);
    }
};

Becomes this:

new UriNotifier(Task.TABLE, Tag.TABLE) {
    @Override
    protected boolean accumulateNotificationObjects(Set<Uri> uris,
            SqlTable<?> table, SquidDatabase database, DBOperation operation,
            AbstractModel modelValues, long rowId) {
        // Should return true if any new objects have been accumulated
        return uris.add(Task.CONTENT_URI);
    }
};
  • DatabaseDao's registerUriNotifier, unregisterUriNotifier, etc. have been replaced with SquidDatabase methods registerDataChangedNotifier, unregisterDataChangedNotifier, etc.
  • SimpleDataChangedNotifier is introduced as an alternative to UriNotifier that simply runs arbitrary code as a callback after a successful write/transaction.
  • Users can subclass DataChangedNotifier to implement their own notification system if necessary

Some simplifications to bulk delete and update

To delete or update all rows in a table, users would have to use the special Criterion.all object. This object had some unexpected performance characteristics (i.e. it slowed down execution of the underlying SQL), and so has been removed. Instead, to update or delete all rows, users can use these new methods:

dao.deleteWhere(Model.class, Criterion.all);
// becomes...
database.deleteAll(Model.class);

dao.update(Criterion.all, template);
// becomes...
database.updateAll(template);

dao.count(Model.class, Criterion.all);
// becomes...
database.countAll(Model.class);

Ability to connect to a custom SQLite build

With stock Android, you're pretty much stuck with the build of SQLite that comes with the phone. In SquiDB 2.0, we've added the ability to build SQLite from source using the NDK and Android SQLite Bindings project from the SQLite developers, and connect to that version of SQLite from your SquidDatabase instances.

This feature is completely optional--by default, SquidDatabase will still connect to the version of SQLite that comes with the phone. We've provided default implementations of adapter classes for connecting to custom SQLite builds in the new squidb-sqlite-bindings project. This project includes the source code from the Android SQLite Bindings project, builds from the SQLite amalgamation files, and includes adapters for plugging in to SquidDatabase. You can use it as-is or swap in a different version of the amalgamation files and compile yourself. Actually connecting it to SquidDatabase is dead simple:

In build.gradle:

compile project(':squidb-sqlite-bindings')

In your SquidDatabase subclass:

public class MyDatabase extends SquidDatabase {
    @Override
    protected DatabaseOpenHelper getDatabaseOpenHelper(Context context,
            String databaseName, DatabaseOpenHelperDelegate delegate,
            int version) {
        return new SQLiteBindingsDatabaseOpenHelper(context, databaseName,
            delegate, version);
    }

    // Other overridden methods
}

Enhanced code generation plugin API

The SquiDB code generator now supports a significantly more robust plugin API for adding custom functionality to SquiDB's code generation process. Users can write plugins to add nearly arbitrary code to generated models. Much of SquiDB's default code generation has also been reimplemented as a set of plugins, many of which can be disabled using a compile-time option if the behavior is not desired. For more information, see the wiki page.

SquidRecyclerAdapter and changes to SquidCursorAdapter

  • Introduced a squidb-recyclerview module. This module depends on the v7 recyclerview support library and implements a version of RecyclerView.Adapter paired with a SquiDB version of ViewHolder that holds a model object in addition to the view. This model object is populated for each row before binding the view as a convenience.
  • SquidCursorAdapter no longer takes a Context in its constructor
  • SquidCursorAdapter no longer requires an _id column to fulfill the getItemId() contract. If one is provided, it will be used and hasStableIds will return true; otherwise, hasStableIds will return false. If the model instance passed to the adapter constructor is a TableModel, that table's id property will be used by default.