我已经阅读了Anko SQLite的文档。

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

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

如何获得简单的MapRowParser

最佳答案

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

第一个文件包含以下内容:

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

其中将MapRowParser显示为接口(interface)。

然而。根据搜索,有两个文件提到了MapRowParser。如果浏览文件,将会发现没有类。根据显示该类的手动实现的this question的说明,必须手动实现该类。此外,Anko的代码未显示任何实现MapRowParser的类。

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

与RowParser等效。这是一个界面。但是,there is a method that returns a specific parser。但是,RowMapParser没有类似的东西。

编辑:

进入the source code表明这两种类型的单行解析器用于几种不同的类型。我认为没有MapRowParser的原因是因为编写一个好的通用 map 解析器太难了。映射通常具有不同的行为,因为它们具有键和值,而列表仅具有您转换为类型并返回的值:
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
    }
}

您可以对 map 执行相同的操作,但是密钥会丢失。此外,检查源代码后,您会发现传递到解析器的数据仅包含一列。

进一步研究源代码也可以揭示此方法:
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
...

系统在游标上运行,可以在解析List或Map中的多个条目的方法中看到这些游标:
moveToFirst()
while (!isAfterLast) {
    list.add(parser.parseRow(readColumnsMap(this)))//adds the result into a pre-defined list to return
    moveToNext()
}

这再次表明编写泛型非常困难,因为必须有一个有意义的返回值,如果您不知道将哪种数据放入单个返回值中,则很难做到这一点。

这对于编写通用解析器来说太难了*,因为您永远无法确定行数,值将要做什么等。因此,为了编写自己的解析器,您需要创建一个实现MapRowParser的类,并使用该类来解析所需的数据。通过为存储为Blob的类分配ID来为实例创建实例,然后将数据放入数据类中,无论使用何种形式。

*这太难写了,因为您永远无法确定一位开发人员将如何使用数据。当您将其作为 map 使用时,您不仅可以返回单个值,
因为其他所有数据都会丢失。因此,如果通用解析器需要它,则必须将其作为 map 返回,然后开发人员仍然不得不解析数据。使用列表很容易返回一个值。但是使用Maps时,为了不丢失任何数据,如果解析器是出于标准化目的而编写的,则它实际上变得无用。

08-05 19:19