Typesafe Activator

Slick with Android Example

Slick with Android Example

pulsation
Source
February 24, 2014
slick android scala basics

A quick example that uses Slick on Android to store data through the SQLDroid JDBC driver.

How to get "Slick with Android Example" on your computer

There are several ways to get this template.

Option 1: Choose slick-android-example in the Typesafe Activator UI.

Already have Typesafe Activator (get it here)? Launch the UI then search for slick-android-example in the list of templates.

Option 2: Download the slick-android-example project as a zip archive

If you haven't installed Activator, you can get the code by downloading the template bundle for slick-android-example.

  1. Download the Template Bundle for "Slick with Android Example"
  2. Extract the downloaded zip file to your system
  3. The bundle includes a small bootstrap script that can start Activator. To start Typesafe Activator's UI:

    In your File Explorer, navigate into the directory that the template was extracted to, right-click on the file named "activator.bat", then select "Open", and if prompted with a warning, click to continue:

    Or from a command line:

     C:\Users\typesafe\slick-android-example> activator ui 
    This will start Typesafe Activator and open this template in your browser.

Option 3: Create a slick-android-example project from the command line

If you have Typesafe Activator, use its command line mode to create a new project from this template. Type activator new PROJECTNAME slick-android-example on the command line.

Option 4: View the template source

The creator of this template maintains it at https://github.com/pulsation/slick-android-example#master.

Option 5: Preview the tutorial below

We've included the text of this template's tutorial below, but it may work better if you view it inside Activator on your computer. Activator tutorials are often designed to be interactive.

Preview the tutorial

Setup

Before compiling this quick example, you have to install SBT and the Android SDK.

If this example doesn't compile within the activator, you may have to configure an Android target manually in its directory. Available Android targets can be listed by issuing the following command :

$ android list targets

Then, you can pick up one for this project with :

$ android update project -p . -t <target>

After that, you can connect your phone or launch an emulator, and run this example by executing :

$ sbt android:run

More information is avaliable on pfn's Android SDK plugin for SBT.

Table definition

Let's look at the src/eu/pulsation/slickexample/SlickAndroidExample.scala file.

In this example, a simple table containing 2 fields is defined. ID is its primary key, and SOME_TEXT contains a line of text.

class MyData(tag: Tag) extends Table[(Int, String)](tag, TableName) {
  def id = column[Int]("ID", O.PrimaryKey, O.AutoInc) // This is the primary key column.
  def name = column[String]("SOME_TEXT")
  // Every table needs a * projection with the same type as the table's type parameter.
  def * = (id, name)
}

You can browse Slick documentation's Getting Started section for more information.

Connecting to the SQLite database

SQLDroid is used here as a JDBC driver provider for SQLite on Android. getApplicationContext().getFilesDir() points to a directory that is writable by our application.

lazy val db = Database.forURL("jdbc:sqlite:" +
    getApplicationContext().getFilesDir() +
    "slick-sandbox.txt", driver = "org.sqldroid.SQLDroidDriver")

Table creation

The table instance's ddl component represents the table's schema description, and is used to create this schema in the SQL database.

myData.ddl.create

Manipulating data

Data can be manipulated with Slick in a similar way to common Scala collections. For more information, you can watch Stefan Zeiger's slick webinar.

 Explicit session

In this case, the session is explicitly passed as a parameter to the function that manipulates data.

val session = db.createSession()
// Delete all rows
myData.delete(session)

 Implicit session

Here, instructions are wrapped in a withSession {} block so that the session is implicitely available while manipulating data.

db withSession {
  implicit session =>
  // Get existing rows
    myData.list
}

Auto Incremented column

As the ID column is marked as AutoInc, its value (0 here) will be ignored and replaced.

db withSession {
  implicit session =>
    // Add a row to the existing data set
    myData += (0, mEdit.getText().toString)
}

Implicit conversion to Runnable

In Android, the UI can only be updated in the UI thread. In Java, this would be expressed this way:

runOnUiThread(new Runnable() {
  public void run() {
    ...
  }
});

In order to minimize the needed amount of code, it is possible in Scala to implicitly convert our Activity class into a Runnable whenever one if its method is called as a parameter of runOnUiThread().

implicit def toRunnable[F](f: => F): Runnable = new Runnable() { def run() = f }

As a result, any method can now be directly called in the UI thread.

runOnUiThread({ displayDataList(rows) })

Futures

Executing blocking tasks on the main UI thread would make the application unresponsive. As an alternative to Android's AsyncTask, it is possible to wrap blocking tasks in Scala Futures.

val fProcessData = Future { process() }

The onSuccess {} block will be executed once a future is completed and returned a result.

fFetchData onSuccess {
    case rows =>
      runOnUiThread({ displayDataList(rows) })
}
comments powered by Disqus