Anko 中的简单 MapRowParser 是什么?

What is a simple MapRowParser in Anko?

我已阅读 Anko SQLite 的文档。

我知道可以通过 val rowParser = classParser<Person>()

创建一个简单的 RowParser

类解析器是 Anko-SQLite 源代码中定义的函数。

如何获得简单的MapRowParser

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

第一个文件包含:

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

其中将 MapRowParser 显示为一个界面。

不过。根据搜索,有两个文件提到了 MapRowParser。如果您查看这些文件,您会发现没有 classes。根据显示 class 的手动实现的 ,它必须手动实现。此外,Anko 的代码没有显示任何实现 MapRowParser 的 classes。

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


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

编辑:

进入the source code表明两种类型的单行解析器用于几种不同的类型。我认为没有 MapRowParser 的原因是因为编写一个好的通用地图解析器太难了。地图通常有不同的行为,因为它们有一个键和一个值,而列表只有一个值,您可以将其转换为类型和 return:

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
...

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

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

这再次表明编写泛型很难,因为必须有一个有意义的 return 值,如果您不知道要将哪种数据放入单个 return 值。

这太难了*,无法为其编写通用解析器,因为您永远无法确定行的数量、如何处理这些值等。因此,为了编写您自己的解析器解析器,您创建一个实现 MapRowParser 的 class 并使用它来解析您需要的数据。例如,通过将 ID 分配给存储为 blob 的 class,将数据放入数据 class 中,无论您将其用于什么用途。

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