Upload
jan-berkel
View
10.181
Download
0
Embed Size (px)
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
Scala for Java Refugees,D. Spiewak
• http://www.codecommit.com/blog/scala/roundup-scala-for-java-refugees
Community
• scala-lang.org, #scala
• very responsive & helpful
• growing the language is a community effort
• eclipse: http://www.novoda.com/blog/?p=154
• simple-build-tools (sbt) http://github.com/harrah/android-plugin
• scala-android: http://code.google.com/p/scala-android/