2009-11-26 10:26 墳墓 (Brian Hsu)
退伍了,終於有比較多的時間可以東摸西搞了,想當然爾,現在的我想玩的,就是 Scala + Android 啦!
Android 確實是個很不錯的平台,可是也有他弱的地方,其中我最不喜歡的,就數 Content Provider 啦。
在 Content Provider 的架構下,的確可以達到不同應用程式間溝通的的做用,可是操作的階層實在是太低了,竟然直接動到資料庫的指標去了。
這對於已經漸漸習慣了 Functional 的我而言,真的是很痛苦啊,想到要在那邊 move 來 move 去,就一整個煩人。
幸好,這個時候,很強大的 trait 就登場啦,只要下面短短幾行的程式,馬上就可以把 Cursor 變成 Functional 啦!
class CursorSeq (cursor: Cursor) extends Seq[Cursor] { require (cursor.moveToFirst) override val length = cursor.getCount override val elements = new Iterator[Cursor] { override def hasNext = !cursor.isLast && !cursor.isAfterLast && !cursor.isClosed override def next : Cursor = { cursor.moveToNext() cursor } } override def apply (n: Int) : Cursor = { cursor.moveToPosition (n) cursor } }
然後,再配上一些 Wrapper class……
case class ReminderItem private (id: Int, title: String, description: String, triggerTime: Int, maidID : String) { def uri : Uri = Uri.parse (Reminder.ContentUri + "/" + id) } object ReminderItem { private def get (cursor: Cursor) : Option[ReminderItem] = { if (cursor == null) { return None } val colID = cursor.getColumnIndex (Reminder.ID) val colTitle = cursor.getColumnIndex (Reminder.Title) val colDescription = cursor.getColumnIndex (Reminder.Description) val colTriggerTime = cursor.getColumnIndex (Reminder.TriggerTime) val colMaidID = cursor.getColumnIndex (Reminder.MaidID) val id = cursor.getInt (colID) val title = cursor.getString (colTitle) val description = cursor.getString (colDescription) val triggerTime = cursor.getInt (colTriggerTime) val maidID = cursor.getString (colMaidID) Some (ReminderItem (id, title, description, triggerTime, maidID)) } def getAll (context: Context) : Seq[Option[ReminderItem]] = { var result : Seq[Option[ReminderItem]] = Nil val cursor = new CursorSeq (context.getContentResolver. query (Reminder.ContentUri, null, null, null, null)) for (row <- cursor) yield get (row) } }
就可以寫出 Functional,並且超簡潔的程式啦!例如:
val item = ReminderItem.getAll.filter (_ != None) // 取出標題是 Hello 的 ReminderItem item.filter (i => i.title == "Hello") // 取出所有 ReminderItem 的 Title item.map ( i => i.title)
這樣比起直接下 Query 來得清楚多囉。
回響