#導覽列 #文章列表 #許洛豪
在光之翼的守護下訴說著一段段的英雄傳說。 [ 首頁 | 網誌 | 相簿 | 留言 | 訂閱 ]

[Android] 實現 Functional 的 Cursor。

退伍了,終於有比較多的時間可以東摸西搞了,想當然爾,現在的我想玩的,就是 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 來得清楚多囉。

將本文加入 Hemidemi 書籤
Brian Hsu (墳墓)
2009-11-26 (週四) 10:26:29


留下迴響







請勿使用注音文或火星文!並請遵守發規則,本站亦不歡迎匿名留言。