Anko中的简单MapRowParser是什么?

时间:2017-11-05 06:57:26

标签: android kotlin anko

我已阅读Anko SQLite的文档。

我知道创建一个简单的RowParser可以通过val rowParser = classParser<Person>()

来完成

classParser是Anko-SQLite源代码中定义的函数。

我怎样才能得到一个简单的MapRowParser

1 个答案:

答案 0 :(得分:6)

如果你继续使用Github并做this search,你会看到有两个文件以任何方式引用MapRowParser。

第一个文件包含:

interface MapRowParser<out T> {
    fun parseRow(columns: Map<String, Any?>): T
}

将MapRowParser显示为界面。

然而。根据搜索,有两个文件提到了MapRowParser。如果你查看文件,你会发现没有课程​​。根据{{​​3}}显示类的手动实现,它必须手动实现。此外,Anko的代码不显示任何实现MapRowParser的类。

因此,您必须创建一个自己实现MapRowParser的类。如果我已经正确地阅读了文档和代码,那么地图本身会自动传递,但解析器所做的是处理您收到的数据。

与RowParser等效。这是一个界面。但是,this question。但是,RowMapParser没有类似的东西。

修改

进入there is a method that returns a specific parser表明两种类型的单行解析器用于几种不同的类型。我认为没有MapRowParser的原因是因为写一个好的,通用的地图解析器太难了。地图通常具有不同的行为,因为它们具有键和值,而List仅具有您作为类型转换的值并返回:

private class SingleColumnParser<out T> : RowParser<T> {
    override fun parseRow(columns: Array<Any?>): T {
        if (columns.size != 1)
            throw SQLiteException("Invalid row: row for SingleColumnParser must contain exactly one column")
        @Suppress("UNCHECKED_CAST")
        return columns[0] as T//Right here it just casts the column as the type defined when creating
    }
}

您可以对地图执行相同操作,但密钥会丢失。此外,通过检查源代码,您会看到传递给解析器的数据只包含一列。

进一步深入研究来源也揭示了这种方法:

private fun readColumnsMap(cursor: Cursor): Map<String, Any?> {
    val count = cursor.columnCount
    val map = hashMapOf<String, Any?>()
    for (i in 0..(count - 1)) {
        map.put(cursor.getColumnName(i), cursor.getColumnValue(i))
    }
    return map
}

如果我已经正确读取了源代码,则上述方法将整行转换为单个Map,并使用该列的名称。所以你最终会得到这样的东西:

Col1 -> Row1col1val
Col2 -> Row1col2val
...

系统在游标上运行,可以在解析列表或地图中的多个条目的方法中看到:

moveToFirst()
while (!isAfterLast) {
    list.add(parser.parseRow(readColumnsMap(this)))//adds the result into a pre-defined list to return
    moveToNext()
}

这又表明编写泛型很难,因为必须有一个有意义的返回值,如果你不知道将哪种数据放入一个返回值,这很难做到。

这对于编写通用解析器来说太难了,因为你永远无法确定行的数量,要对值做什么等等。所以为了编写自己的解析器,您创建一个实现MapRowParser的类,并使用它来解析您需要的数据。通过将ID分配给存储为blob的类,将数据放入数据类(无论您使用它是什么)来实例化。

*写起来太难了,因为你永远无法确定一个开发人员将如何需要这些数据。当你将它作为地图时,你不能只返回一个值,  因为所有其他数据都会丢失。因此,如果需要一般的解析器,则必须将其作为映射返回,然后开发人员仍然必须解析数据。通过列表,只需返回单个值即可。但是对于Maps,为了不丢失任何数据,如果它是为标准化目的而编写的,那么解析器基本上就没用了。