Skip to content
Siim Kinks edited this page Apr 11, 2020 · 5 revisions

Minimal Setup

Install IntelliJ Plugin:

The Intellij plugin can be installed from Android Studio by navigating Android Studio -> Preferences -> Plugins -> Browse repositories -> Search for SqliteMagic

IntelliJ plugin adds visual support for "automagically" generated methods aka removes "method not found" messages.

Add SqliteMagic to Project:

buildscript {
  repositories {
    jcenter()
  }
  dependencies {
    classpath 'com.android.tools.build:gradle:<latest version>'
    classpath 'com.siimkinks.sqlitemagic:sqlitemagic-plugin:<latest version>'
  }
}

apply plugin: 'com.android.application'
apply plugin: 'com.siimkinks.sqlitemagic'

Gradle plugin hooks SqliteMagic bytecode transformer into the project build system and adds required SqliteMagic dependencies in the right configuration to your project.

Initialize Library:

SqliteMagic.builder(applicationContext)
  .sqliteFactory(new FrameworkSQLiteOpenHelperFactory())
  .openDefaultConnection();

Any place with a reference to Application context is ok to use for initialization, but it must happen before a database is accessed. During initialization default db connection is opened, db schema is created and migration scripts are executed - no other hidden runtime performance costs.

AND THAT'S IT FOR MINIMAL SETUP REQUIREMENTS! - ONE CAN NOW START USING SQLITEMAGIC


Additional Setup Options

Configure Database

With default configuration database is named database.db, has version number 1 and logging is disabled.

Annotation

Database name and version can be configured by defining @Database annotation on any class or interface.

@Database(
    name = "sample.db",
    version = 2)
public interface DatabaseConfiguration {}

During Initialization

Database name can also be configured during initialization, but this method is more meant to be used for opening multiple database connections.

SqliteMagic.builder(applicationContext)
    .name("sample.db")
    .openDefaultConnection();

Database name is determined in the following order: during initialization > annotation > default value.

Setup Logging

By default logging is disabled.

Logging can be enabled statically:

SqliteMagic.setLoggingEnabled(true);

By default SqliteMagic uses the default logger. If special logging is needed implement Logger interface and tell SqliteMagic about it:

SqliteMagic.setLogger(myDefaultLogger);

Configure Gradle Plugin

SqliteMagic provides the following configuration options for Gradle plugin. If you need to configure any of these settings, you can add a block like the following to configure the plugin:

sqlitemagic {
  configureAutomatically = true
  generateMagicMethods = true
  useKotlin = true
  publicKotlinExtensionFunctions = false
  generateLogging = true
  autoValueAnnotation = "com.google.auto.value.AutoValue"
  debugBytecodeProcessor = false
}
  • configureAutomatically Setting this to false will not add Sqlitemagic dependencies automatically to the project, which means all dependencies must be configured manually. The default is true.
  • generateMagicMethods Setting this to false will not generate any "magic" extension methods. The default is true.
  • useKotlin Setting this to false tells Sqlitemagic not to add kotlin related Sqlitemagic dependencies to the project even if kotlin is configured for the project. The default is true.
  • publicKotlinExtensionFunctions Setting this to true generates kotlin extension functions for table with public visibility modifiers. When setting this to false the extension functions will have internal visibility modifiers. The default is false.
  • generateLogging Setting this to false tells the annotation processor not to generate any logging statements. The default is true.
  • autoValueAnnotation Set AutoValue library annotation fully qualified name. Change this configuration only when using any AutoValue library fork that does not share the fully qualified name with the original one. The default is com.google.auto.value.AutoValue.
  • debugBytecodeProcessor Setting this to true will make the bytecode processor log more information to console. The default is false.

For Multi-Module Projects:

If project is divided into multiple modules then there is some additional configuration to be done.

For example lets take a project that is divided into 3 modules:

  • app Contains all views and top level logic.
  • business Contains all business logic, use cases and models used throughout the app.
  • data Contains all information how to get, save and modify data, etc.

Dependency tree among modules is as follows:

    business
  ↗      ↑
app ⟶ data

If that ascii art is unclear then app depends on business and data; data depends on business and business is independent.

For business module apply the normal setup. For the sake of this example lets say that in this module there are also all the persistable database models.

buildscript {
  repositories {
    jcenter()
  }
  dependencies {
    classpath 'com.android.tools.build:gradle:<latest version>'
    classpath 'com.siimkinks.sqlitemagic:sqlitemagic-plugin:<latest version>'
  }
}

apply plugin: 'com.android.library'
apply plugin: 'com.siimkinks.sqlitemagic'

This configuration places all the annotation processor generated code in the business module.

Next, we want to access the database in the data module. In order to do that configure it as follows:

apply plugin: 'com.android.library'

...

dependencies {
  ...
  provided 'com.siimkinks.sqlitemagic:sqlitemagic:<latest version>'
}

This configuration gives access to runtime library methods needed to access the database.

Finally, we want to initialize library in the app module. In order to do that configure it as follows:

apply plugin: 'com.android.application'
apply plugin: 'com.siimkinks.sqlitemagic'

This configuration hooks bytecode processor into the build system.

And initialize SqliteMagic the usual way.

For example:

public final class MyApplication extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    SqliteMagic.builder(this)
        .sqliteFactory(new FrameworkSQLiteOpenHelperFactory())
        .openDefaultConnection();
  }
}

When database models are located across many modules

When database models are located across many modules there is a bit of extra configuration to be done:

  • Each submodule must have exactly one class/interface with the @SubmoduleDatabase annotation.
@SubmoduleDatabase("submodule")
public interface SubmoduleDatabaseConfig {}
  • The main "data" module must have exactly one class/interface with the @Database annotation which references the submodules annotated classes/interfaces.
@Database(submodules = { SubmoduleDatabaseConfig.class })
public interface DatabaseConfig {}

Clone this wiki locally