Programming Android with Scala

As I've mentioned in my previous blog post, I am working on several Android projects. Once you've done some larger projects and you have already worked with alternative JVM languages like Groovy [0] or Scala [1], one quickly feels the need for reducing common code patterns found in every Android project. That was the main reason I chose to use Scala as main programming language for one of my free-time Android projects. This article is about my experiences with Scala and the language features I found most useful when working with the Android framework.

Environment and Prerequisites

First of all: I am an IntelliJ user, working on a MBP. I did not test how writing an Android app with Scala works out in Eclipse. I usually develop all my Android projects in IntelliJ as Eclipse and the Android plugin just did not work out for me (it constantly slows down, hangs, of course your mileage may vary). I installed the android-sdk, scala, sbt etc. with Homebrew
 brew install scala sbt android-sdk 
and worked with the following package/software versions:

Setting up the project structure and environment

First of all: I don't want to scare you right away, but neither IntelliJ nor Eclipse (to my knowledge) offers support for developing Android projects with Scala in a continuous process from project creation to APK creation. There is no out-of-the-box configuration, you'll need to have some manual or scripted steps when developing outside the standard Android environment. On the other side, IntelliJ offers seperate module facets for Android and Scala projects. When combining the Scala and Android facet you'll get syntax completion for Scala and Android-specific files, automatic R.java file compilation, sbt APK debug package generation (with a separate run configuration) and, well, the joy to use Scala instead of Java for your Android project ;). I don't want to go into details of IntelliJ module configuration, but in case you chose to work with sbt [3] you can use a giter8 template [2] to jump-start with an sbt supported project structure holding an empty Android application and test setup (for more information see [4]).

Using Scala for your Activity classes

Once you are done setting up the environment, you can start with your first activity, let's call it HomeActivity. Let's take a look at the Java implementation.
 
public class HomeActivity extends Activity {

    public void onCreate(Bundle savedState)  {
        super.onCreate(savedState);
        setContentView(R.layout.home);
    }
}
 
Since we do need some UI widgets, we will add a login and password EditText field and a Button and add the according code to the Activity class:
 
public class HomeActivity extends Activity {

private EditText usernameEditText;
private EditText passwordEditText;
private Button   loginButton;

public void onCreate(Bundle savedState)  {
  super.onCreate(savedState);
  setContentView(R.layout.home);

  usernameEditText = (EditText) findViewById(R.id.usernameEditText);
  passwordEditText = (EditText) findViewById(R.id.passwordEditText);
  loginButton = (Button) findViewById(R.id.loginButton);
}
}

 
Next we'll register a View.OnClickListener to react on button clicks/touches:
 

public class HomeActivity extends Activity {

private EditText usernameEditText;
private EditText passwordEditText;
private Button   loginButton;

public void onCreate(Bundle savedState)  {
  super.onCreate(savedState);
  setContentView(R.layout.home);

  usernameEditText = (EditText) findViewById(R.id.usernameEditText);
  passwordEditText = (EditText) findViewById(R.id.passwordEditText);
  loginButton = (Button) findViewById(R.id.loginButton);

  loginButton.setOnClickListener(new View.OnClickListener() {
    public void onClickListener(View view)  {
        // do some validation stuff

        startActivity(new Intent(HomeActivity.this, NextActivity.class));  
    }
  });
}
}

 
That's it for now with our sample Java-based activity. Now let's see how the same Activity can be done using the Scala programming language. As can bee seen from the source samples above, Java quickly produces very bloated code. When working with the Android framework that bloat is typically driven by type casts, anonymous class definitions, inner class definitions, common code to initialize menu items, etc. Let's translate the HomeActivity into a Scala class. First of all we'll consider getting rid of the findViewById method calls and the type casts that have to be done for the return types. The sbt Android plugin generates a special singleton object for that purpose: the TR (typed resources) object. Within that class it creates typed references of type TypedResource for all the UI elements defined in the application's XML layout files.
 
case class TypedResource[T](id: Int)

object TR {
  val usernameEditText = TypedResource[EditText](R.id.usernameEditText)
  val passwordEditText = TypedResource[EditText](R.id.passwordEditText)

  val loginButton = TypedResource[Button](R.id.loginButton)  
}

trait TypedViewHolder {
  def view: View
  def findView[T](tr: TypedResource[T]) = view.findViewById(tr.id).asInstanceOf[T]
}

trait TypedView extends View with TypedViewHolder { def view = this }

trait TypedActivityHolder {
  def activity: Activity
  def findView[T](tr: TypedResource[T]) = activity.findViewById(tr.id).asInstanceOf[T]
}

trait TypedActivity extends Activity with TypedActivityHolder { def activity = this }

object TypedResource {
  implicit def view2typed(v: View) = new TypedViewHolder { def view = v }
  implicit def activity2typed(act: Activity) = new TypedActivityHolder { def activity = act }
}
 
The TR object defines typed source objects for all XML defined widgets and some traits to be reused in activity classes and views. Once the TR class is generated by sbt we can use the TypedActivity trait (more about traits in a short moment) to reference our UI widgets in a type-safe way:
 

class HomeActivity with TypedActivity {

   override def onCreate(savedState: Bundle) {
      super.onCreate(savedState)
      
      val usernameEditText = findView(TR.usernameEditText)
      val passwordEditText = findView(TR.passwordEditText)
      val loginButton = findView(TR.loginButton)

      // ...
   }
}

 
In case you are wondering where the findView method comes from, it is defined by TypedActivity. In comparison to the Java implementation we have saved the type casts. Now let us register the button click listener.
 

class HomeActivity with TypedActivity {

   override def onCreate(savedState: Bundle) {
      super.onCreate(savedState)
      setContentView(R.layout.home)
      
      val usernameEditText = findView(TR.usernameEditText)
      val passwordEditText = findView(TR.passwordEditText)
    
      val loginButton = findView(TR.loginButton)
      loginButton.setOnClickListener(new View.OnClickListener() {

       override def onClickListener(View view)  {
           startActivity(new Intent(HomeActivity.this, classOf[NextActivity]))  
         }
       })
     }
}

 
OOOOkay - there is not much difference compared to the Java implementation, that's true. But now comes the interesting part. Scala provides certain languages features which allow you to greatly reduce code. And here comes a list with my top-five favorite Scala language features. Please note that I do not consider myself being a Scala expert - I would say I have average Scala knowledge. There might be better ways that lead to better results, please feel free to post them in the article's comment section!

Favorite 1: Lazy Vals

As you can see in the code sample above, we have still the burden to use findView in the onCreate method. If we wanted other methods to access these references we would have to introduce instance variables, which again increases our LOCs. We can avoid that circumstance by using so-called lazy vals. In fact, Scala provides a keyword for specifying lazy attributes: not surprisingly, lazy.
 
class HomeActivity with TypedActivity {

   lazy val usernameEditText = findView(TR.usernameEditText)
   lazy val passwordEditText = findView(TR.passwordEditText)
    
   lazy val loginButton = findView(TR.loginButton)

   override def onCreate(savedState: Bundle) {
      super.onCreate(savedState)
      setContentView(R.layout.home)
      
      loginButton.setOnClickListener(new View.OnClickListener() {

       override def onClickListener(View view)  {
           startActivity(new Intent(HomeActivity.this, classOf[NextActivity]))  
         }
       })
     }
}
 
This makes all UI element lookup operations lazy, meaning that the widget reference is looked up only once on first access during runtime. If the lazy instance variable is not accessed, the findView method will not be executed, therefore saving lookup operations. In the example above, we could even further defer the registration of the OnClickListener:
 
class HomeActivity with TypedActivity {

   lazy val usernameEditText = findView(TR.usernameEditText)
   lazy val passwordEditText = findView(TR.passwordEditText)
    
   lazy val loginButton = {
      val b = findView(TR.loginButton)
      b.setOnClickListener(new View.OnClickListener() {

       override def onClickListener(View view)  {
           startActivity(new Intent(HomeActivity.this, classOf[NextActivity]))  
         }
       })

       b
   }

   override def onCreate(savedState: Bundle) {
      super.onCreate(savedState)
      setContentView(R.layout.home)
    }
}
 

Favorite 2: Implicit type conversions

Wouldn't it be nice to implement the View.OnClickListener interface with a Scala function, like that
 

     loginButton.setOnClickListener((v: View) => startActivity(new Intent(HomeActivity.this, classOf[NextActivity])))

 
To be honest, in a real world example you would have to enclose the functions body with curly braces (the example uses a single statement in the function body), but at least we got rid of the method interface declaration. The code above can be left as it is, by introducing an implicit type conversion.
 

implicit def function2ViewOnClickListener(f: View => Unit) : View.OnClickListener = {

   new View.OnClickListener() {
     def onClick(view: View) {
       f(view)
     }
   }

}

 
As long as the implicit conversion is in the appropriate scope every function from source scope View to target scope Unit will be automatically converted to an instance of the anonymous class implementing the View.OnClickListener interface. Of course there are bunch of interfaces to write implicit conversions for, in my first Scala Android project I put them all in a trait to reuse them accross activities.

Favorite 3: Traits

A Java interface is very abstract. It is as abstract as an interface can be (even the interface contracts are omitted ;)). An abstract class is better in a way that it can provide method implementations, but than the problem swaps over to single inheritance as you can't use multiple abstract classes as parent classes. When your classes are defined in a framework context, this gets a real problem because the single inheritance line is most of the time already reserved for framework descending classes, meaning that custom classes extending from framework classes can't extend custom classes anymore. That reuse restriction causes by single inheritance strikes me with its full power in my Java-based Android projects. Let us assume that we need to extend both, class Activity and class ListActivity. Since the framework and Java's single inheritance mechanism forces us to extend both activity classes, there is no way to extend from a common OptionsMenu base class that uniformly creates the application options menu. With Scala we can create a so-called trait. A trait can be imagined as an abstract or concrete class that can be mixed into another class. A Scala class can mix-in several traits, but can only extend from a single descendant class. The Scala guys to to speak of "mix-in classes" instead of "multiple inheritance of classes" since traits differ in some ways from how multiple inheritance is implemented in other programming languages. A trait for the OptionsMenu could be written as:
 
trait OptionsMenu extends Activity {

  override def onCreateOptionsMenu(menu: Menu) : Boolean = {
    menu.addSubMenu("Test")

    true
  }
}

 
The trait can now be used in all classes that directly or indirectly extend from Activity - and this includes ListActivity!
 
class NextActivity extends ListActivity with OptionsMenu {

  // ...
}
 
Another example would be further shortening the code for our HomeActivityby providing a base trait that extends from TypedActivity and the newly created OptionsMenu trait.
 
trait Activity with TypedActivity with OptionsMenu {

  lazy val usernameEditText = findView(TR.usernameEditText)
  lazy val passwordEditText = findView(TR.passwordEditText)
  lazy val loginButton = findView(TR.loginButton)

  val contentView: Int

  val init: Unit

  override def onCreate(savedInstanceState: Bundle) {
    setContentView(contentView)

    init
  }
}
 
Wit the base class shown above the HomeActivity can be minimized to the following code piece.
 
class HomeActivity extends Activity {

  val contentView: Int = R.layout.activity_home

  val init = {
    loginButton.setOnClickListener( (v: View) => startActivity(new Intent(HomeActivity.this, classOf[NextActivity] )))
  }
}
 
If we compare this class with our initial Java class in the first source code example, you'll see that with the help of lazy vals, implicit conversions and traits we already reduced the source code to a great extent.

Favorite 4: Pattern matching and Case Classes

If you have ever taken a look at Erlang you'll have with no doubt a clear picture of how integral pattern matching can be a very characteristic programming language property. Scala provides various pattern matching mechanisms by providing the match and case keywords.
 

override def onCreateDialog(dialogId: Int) : Dialog = {
   dialogIg match {
     case SHOW_ALERT_DIALOG => // create the dialog instance
     case _ => throw new IllegalArgumentException("Dialog " + dialogId + " could not be created!")
   }
}

 
Pattern matching in Scala is mighty. It does not work for integer values only, it works for strings and various other types [5]. A special case of pattern matching can be realized with so-called case classes. A case class defines an immutable type with a pre-generated toString/hashCode/equals method implementations, a factory apply method, and automatic val prefixing. Case classes can be used like good-old records in several corners of the Android framework, e.g. for implementing a view holder.
 
case class ViewHolder (checkBox: CheckBox, textView: TextView)
 

Conclusion

Scala does not aim to be an evolutionary successor of the Java programming language. It is a functional and object-oriented language with its own type system, features and - hard to grasp for hardcore Java hackers at first sight - its own language syntax. On the other hand, the Android SDK is a Java-based framework, naturally using Java concepts and patterns found in other Java frameworks. Scala provides neat features to greatly reduce framework clue code allowing to concentrate on application logic and domain classes. You can find the article's source code examples at Github [6].

[0] The Groovy Programming Language - http://groovy.codehaus.org/
[1] Learning Scala - http://www.scala-lang.org/node/1305
[2] Giter8 Templates - https://github.com/n8han/giter8#readme
[3] SBT Scala Simple Build Tool - https://github.com/harrah/xsbt/wiki
[4] SBT Android Plugin
[5] Scala Pattern Matching - http://www.scala-lang.org/node/120
[6] Scala Android Examples - https://github.com/andresteingress/scala-android-examples