sbt-android-pluginで型安全にリソース取得

ネタ元はここ
http://code.technically.us/post/824974287/rewiring-android-for-type-safe-layout-resources

sbt-android-pluginが0.5.0からTyped resources referencesという便利なものに対応したので紹介。

短く型安全なリソース取得

Scalaでボタンなどのリソースをとってくるのにはいちいち

val button = findViewById(R.id.button).asInstanceOf[Button]

こんな感じに書かないといけない。さすがにこれは長いのでimplicit conversionを使って短く書く方法をここでも紹介した。
この以前紹介した方法は、単に短く書けるというだけで型安全ではなかった。上のコードでいうと本当にButtonオブジェクトへの参照が取得できるかどうかは実行時じゃないとわからなかった。


sbt-android-pluginが0.5.0から提供する機能はこのリソース取得を短く書けて、さらに型安全も提供するすぐれものだ。
この機能を使うと上のコードは

val button = findView(TR.button)

と書けるようになる。しかもButton型の指定がなくてもちゃんとButton型のオブジェクトを返してくれる。


仕組みに関してはネタ元のページに書いてある。簡単に説明すると、ビルド時にリソースファイル(res/layout/*.xml)から型とidを対応つけたTR.scalaというファイルを生成して、それを使ってリソースの取得をおこなう。
ちなみに生成されるTR.scalaはこんな感じ。

case class TypedResource[T](id: Int)
object TR {
  val mapview = TypedResource[com.google.android.maps.MapView](R.id.mapview)
  val list = TypedResource[android.widget.ListView](R.id.list)
  val button = TypedResource[android.widget.Button](R.id.button)
}
// 以下略

使用方法

プロジェクトファイル(project/build/<プロジェクト名>.scala)のMainProjectにTypedResourcesトレイトをmix-in

class MainProject(info: ProjectInfo) extends AndroidProject(info) with Defaults with MarketPublish with TypedResources{
  //...
}

あとはアクティビティクラスにTypedActivityトレイトをmix-inしてやればfindViewが使えるようになる。
Viewに対してfindViewが使いたい場合はimport TypedResources._してやればよい。