Samuel Tardieu @ rfc1149.net

Just because I can

,

People programming for the Android platform know that you are not supposed to perform lengthy operation in the user interface task. You must create a background task, which will interact with your user interface task through a Handler, or you will use a pre-built AsyncTask to ease the interaction.

However, if you chose to use Scala instead of Java to build your Android application, you can easily take advantage of its functional nature to build much more exciting constructs to handle this mandatory parallelism. For example, while developing a piece of code to retrieve the state of my city shared bike stations from the network, I wrote a little piece of utility code based on two functions each taking an expression to run: onBG executes something in a background task, and its companion onUI executes something back in the user interface task. Also, when calling onUI, the result of the given expression can later be used from the background task; if needed, it will block until this result is available.

Here is a short example showing the loading of the bike stations list from the network, then the loading of the state of the first five stations. A progress dialog, part of the user interface, indicates the current state of the background operation. Compare to what you would have needed to write in Java.

// Execute lengthy loading from the network in a background (BG) task as to not
// block the user interface (UI) task.
this.onBG {
  // Create a progress dialog on UI task, and return a pointer to it which, if
  // used, will block as long as needed until the expression has terminated.
  // Otherwise, do not block.
  val progressDialog = this.onUI(ProgressDialog.show(this, "Loading stations",
                                                     "Loading list of stations"))
  try {
    // Load a list of stations from the network (long operation) and keep only
    // five of them.
    val stations = Station.loadFromNetwork.take(5)

    // Change the progress dialog so that now it can be used to indicate
    // the progress while station information is loaded from the network.
    // This has to be done on the UI task. Note that this will wait until
    // the progress dialog creation has terminated if needed, as we use
    // the result of the previous "onUI" call.
    this.onUI {
      progressDialog.setIndeterminate(false)
      progressDialog.setMax(stations.size)
    }

    // For every station…
    for ((station, index) <- stations.zipWithIndex) {
      // …update the progress dialog on the UI task…
      this.onUI {
        progressDialog.setProgress(index)
        progressDialog.setMessage("Loading station details\n" + station.name)
      }
      // …and load its availability from the network.
      station.reloadAvailability
    }
  } finally {
    // Whatever the completion is (regular or exception), dismiss the
    // progress dialog.
    this.onUI(progressDialog.dismiss)
  }
}

Why did I write those two functions? Just because, in Scala, I can.

Don’t wait: try Scala today.

blog comments powered by Disqus