Я пытаюсь выполнить select, используя расширение kotlin
в kotlin
как kotlin
ниже.
fun read() { database.use { select(PersonTable.Name).exec { select("myTable").exec() { parseList( object : MapRowParser<Map<String, Any>> { override fun parseRow(columns: Map<String, Any?>): Map<String, Any> { Log.d("Hello", "Hello") return columns; } } ) } } } }
Я получаю сообщение об ошибке в return column
Type mismatch. Required Map<String, Any> Found Map<String, Any?>
Если я override fun parseRow(columns: Map<String, Any>): Map<String, Any>
то он показывает ошибку.
build.gradle
apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' android { compileSdkVersion 25 buildToolsVersion "25.0.2" defaultConfig { applicationId "com.williams.fourthdemo" minSdkVersion 16 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" compile 'com.android.support:appcompat-v7:25.3.1' testCompile 'junit:junit:4.12' compile 'com.android.support.constraint:constraint-layout:1.0.2' compile "org.jetbrains.anko:anko-common:0.10.1" compile "org.jetbrains.anko:anko-sqlite:0.10.1" }
Это ошибка в библиотеке anko?
Выглядит как
object : MapRowParser<Map<String, Any>> {
должно быть действительно
object : MapRowParser<Map<String, Any?>> {
В базах данных очень часто есть столбцы, которые возвращают нуль в ячейке. То, как вы определили его как Any
null, никогда не произойдет. Если вы вернетесь в Map<String, Any>
то вы просто закончите с ошибками во время выполнения, если нуль будет содержаться где угодно.
Вам лучше всего подходит, сделав его Any?
тип, который заставляет возвращаемый тип parseRow быть Map<String, Any?>
также и исправляет потенциальную ошибку в вашем коде, которая произошла бы, если бы нулевое значение должно было где-то подкрадываться.
columns
имеют тип Map<String, Any?>
, обратите внимание, что Any?
любой объект или null
. Но возвращаемый тип метода – Map<String, Any>
, Any
не может быть null.
Например, вы можете отфильтровать входящую карту, оставив только ненулевые значения: columns.filterValues { it != null } as Map<String, Any>
. Он содержит непроверенный актерский состав, но он безопасен.
Это не ошибка в Anko. Это ошибка в коде.
Эта функция неверна:
override fun parseRow(columns: Map<String, Any?>): Map<String, Any> { Log.d("Hello", "Hello") return columns; }
Вы берете ввод и возвращаете его как есть, но с другим типом.
Ваш ввод имеет тип Map<String, Any?>
Но вы должны каким-то образом преобразовать его в Map<String, Any>
Было бы так, как если бы вы определили функцию, которая принимает String и возвращает Int следующим образом:
fun parseString(s: String): Int { return s }
Это, очевидно, не будет компилироваться.
Интерфейс, который вы пытаетесь реализовать, в основном:
interface MapRowParser<out T> { fun parseRow(columns: Map<String, Any?>): T }
Вы должны предоставить функцию, которая преобразует словарь, представляющий строку базы данных, в какой-то конкретный объект по вашему выбору. Но вы должны фактически предоставить код для обработки.
В качестве альтернативы, Anko предоставляет вам функцию, которая может автоматически сопоставлять строку таблицы с конструктором класса, что я бы предпочел использовать, вместо того, чтобы вручную сопоставлять словарные ключи с полями классов.
data class User(val userId: Int, val userName: String) val rowParser = classParser<User>()