Fork me on GitHub

Wednesday, April 24, 2013

Accessing widgets in view classes

In conventional Android programming, UI widgets are accessed by using findViewById() method as shown below:
var name: EditText = null

override def onCreate(b: Bundle) {
  super.onCreate(b)
  setContentView(R.layout.main)

  name = findViewById(R.id.name).asInstanceOf[EditText]
}

def printName() {
  println("The name is " + name.getText())
}
This causes some major problems:

  • Not type-safe
    You have to manually track the type of the widget, and no compile-time guarantee that you did not made any mistake.
  • The member name is mutable
    It is better to declare name as immutable because it refers only one widget.
  • Possibility of NullPointerException
    Accessing name before calling onCreate() summons NPE-the-horrible!
  • Requires extra XML configurations to maintain
    Use XML layout if you like housekeeping chores.

  • In Scaloid, you can rewrite it with:
    var name: SEditText = null
    
    onCreate {
      contentView = SVerticalLayout {
        name = SEditText("Default name")
      }
    }
    
    def printName() {
      println("The name is " + name.text)
    }
    
    This looks much better, because it is type-safe and eliminates XML configurations. However, the member name is still a mutable variable. It can be improved as shown below:
    lazy val name = new SEditText("Default name")
    
    onCreate {
      contentView = SVerticalLayout {
        this += name
      }
    }
    
    def printName() {
      println("The name is " + name.text)
    }
    
    Now the member name is a lazy value, therefore the possiblilty of NPE is eliminated as well.