Building blocks for Android interactionBuilding blocks for Android interaction

All interactive software should relegate lengthy processes to background threads. In mobile applications this is crucial, as they commonly invoke network operations that can be anything from slow to god-awfully slow. Further, users that are accustomed to momentary freezes in computers are a little less tolerant of apps that do this to their friggin’ phones.

Fortunately multitasking is built into Android at all levels, from long-running services that eventually post user notifications to threads that perform one-second, one-off jobs within a single activity (roughly analogous to a window). This post is concerned with the second, most basic and simple case. And guess what? It’s even more basic and simple in Scala.

While the Android API seems to have approached the problem of modeling graphical interaction with a clean slate—and thank heavens for that—it doesn’t invent things without cause. So to do work in a new thread, you do it however you normally would. In Java this might in involve creating and running a Thread; it Scala it can be abstracted like this:

import scala.actors.Actor._
actor {
  // upload a file or something
}

The interesting part is what happens when the work is done. The background thread can’t interact directly with interface objects in the main thread, so, Android gives us a message queue to communicate with the main thread. It is not so different from what we have in Scala’s actors library! An Android message includes an integer message code, to be compatible with Java’s famously lame switch statement perhaps, but in Scala we can ignore that and use pattern matching to branch on and extract the data, like with actors:

case class Dismiss(dialog: AlertDialog)
val handler = new Handler(new Handler.Callback {
  def handleMessage(message: Message) = message.obj match {
    case Dismiss(dialog) => 
      dialog.dismiss()
      true
      [...]
  }
}
def upload_file {
  val loading = [...indefinite progress dialog]
  actor {
    [upload it and such]
    handler.sendMessage(Message.obtain(handler, 0, Dismiss(loading)))
  }
}

Which is not at all shabby! You could easily factor out more boilerplate, make sendMessage more actor-like by aliasing it to !, and maybe even bridge the queues between Scala actors and Android messages. But now, let’s check out another way that Android lets you beam back from a background thread: posting a Runnable object to the handler queue.

In this case the message that goes into the main thread’s queue is program code, sort of like a block. In Scala we can easily factor out some cruft and pat ourselves on the back for using immutable references that we know will not have been altered before the background thread is done and the main thread gets around to processing the Runnable:

val handler = new Handler
def post(block: => Unit) { 
  handler.post(new Runnable{
    def run { block }
  })
}
def upload_file {
  val loading = [...indefinite progress dialog]
  actor {
    [upload it and such]
    post { loading.dismiss() }
  }
}

The case classes that seemed so smart a hundred words ago are now revealed to be first-class cruft and generally unsavory characters! To use that scheme for every interaction from a background thread you would have to describe most of the Android API in cases classes, which might impress your school mates but not this crowd of elite Coderspiel readers. If we were talking across applications or even activities, instead of dealing with local references, then it would be a different story.

And that concludes this teaser for Androids Dream of Monadic Sheep, the next New York Scala Enthusiasts Meetup.

Add a comment