Android development with Scala

Preview:

Citation preview

Android development with

Scala

@jberkel

Scala?

• a better, more modern Java

• based on the JVM, Java (binary) compatible

• multi-paradigm: functional, oop

• soon mainstream? twitter, ebay...

better?

• purer OO (no primitives)

• less boilerplate ([gs]etter)

• less code (type inference)

• no checked exceptions

• no 1:1 file - class mapping

type inference

Map<String,String> m = new HashMap<String,String>();m.put("foo", "bar");

val m = Map("foo"->"bar")

sound type checking which doesn’t get in your way

traits = fat interfaces

import android.util.Log

trait LogHelper { def log(s: String) = Log.d(getClass.getSimpleName, s) def logException(e: Throwable) = Log.e(getClass.getSimpleName, "error", e) def withExceptionHandling(what: => Unit) { try { what } catch { case ex: Exception => logException(ex) } }}

import android.util.Log

trait LogHelper { def log(s: String) = Log.d(getClass.getSimpleName, s) def logException(e: Throwable) = Log.e(getClass.getSimpleName, "error", e) def withExceptionHandling(what: => Unit) { try { what } catch { case ex: Exception => logException(ex) } }}

what: passed in as function

class MyService extends android.app.Service with LogHelper {

override def onCreate() { withExceptionHandling { log("about to run") doDangerousStuff(true) } }}

trait DbSupport { def getDb: android.database.sqlite.SQLiteDatabase

def query[T](sql: String, args: String*)(fun: Cursor=>T) = { val cursor = getDb.rawQuery(sql, args.toArray[String]) try {

fun(cursor) } finally {

cursor.close } }}

“loan pattern”

traits are “stackable”

class ServiceStack extends Service with DbSupport with LogHelper { // }

functional programming style

use functions instead of one-methodinterfaces !

locationManager.addGpsStatusListener( new GpsStatus.Listener { public void onGpsStatusChanged(int event) { System.out.println(event); }})

locationManager.addGpsStatusListener(println(_))

vs.

pimp my library

cursors

implicit def RichCursor(c: Cursor):RichCursor = new RichCursor(c) class RichCursor(underlying: Cursor) extends Iterable[Cursor] { override def elements = new Iterator[Cursor] { def hasNext = !underlying.isLast def next = { underlying.moveToNext() underlying } } } the trait Iterable

provides find, map, filter etc.

query("select * from foo") { cursor =>cursor.map { row => val v = new ContentValues DatabaseUtils.cursorRowToContentValues(row, v) v}

}

XML handling

val event = <event> <artists> <artist>Screaming Tea Party</artist> <artist>Ungdomskulen</artist> <artist>Invasion</artist> </artists></event>

val artists = (event \ "artist" \ "artists").map(_.text).mkString(", ")

inline XML with xpath style query operator

validate xml at compile time!

Problems• incomplete “convenience” layer

• resulting APKs are big, use proguard

• not many tools / experienced devs

• fewer libraries, but growing

Programming in Scala

Community

• scala-lang.org, #scala

• very responsive & helpful

• growing the language is a community effort

Recommended