【问题标题】:Type mismatch. Required Map<String, Any> Found Map<String, Any?>类型不匹配。必需的 Map<String, Any> 找到的 Map<String, Any?>
【发布时间】:2017-06-11 20:06:52
【问题描述】:

我正在尝试使用kotlin 中的anko 扩展名执行选择,如下所示

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&lt;String, Any&gt;): Map&lt;String, Any&gt;,则会显示错误。

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库中的错误吗?

【问题讨论】:

  • 不知道是不是bug。但要解决这个问题,您可以将columns 映射到新的Map&lt;String, Any?&gt;,然后返回。

标签: android sqlite kotlin anko


【解决方案1】:

看起来像

object : MapRowParser&lt;Map&lt;String, Any&gt;&gt; {

应该是

object : MapRowParser&lt;Map&lt;String, Any?&gt;&gt; {

数据库中的列在单元格中返回空值是很常见的。您将其定义为 Any 的方式意味着 null 永远不会发生。如果您将返回值转换为Map&lt;String, Any&gt;,那么如果任何地方都包含空值,您最终只会发生运行时错误。

您最适合将其设置为 Any? 类型,该类型也强制 parseRow 返回类型为 Map&lt;String, Any?&gt;,并修复了如果空值在某处蔓延时可能发生的代码中的潜在错误。

【讨论】:

    【解决方案2】:

    columns 的类型为Map&lt;String, Any?&gt;,注意Any? 是任何对象或null。但是方法的返回类型是Map&lt;String, Any&gt;Any不能为null。

    例如,您可以过滤传入的地图,只留下非空值:columns.filterValues { it != null } as Map&lt;String, Any&gt;。它包含未经检查的演员表,但它是安全的。

    【讨论】:

      【解决方案3】:

      这不是 Anko 中的错误。这是您代码中的错误。

      这个函数是错误的:

      override fun parseRow(columns: Map<String, Any?>): Map<String, Any> {
          Log.d("Hello", "Hello")
          return columns;
      }
      

      您正在接受输入并按原样返回,但类型不同。

      您的输入是Map&lt;String, Any?&gt; 类型,但您必须以某种方式将其转换为Map&lt;String, Any&gt;

      就好像你定义了一个接受 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>()
      

      【讨论】:

        猜你喜欢
        • 2018-04-12
        • 1970-01-01
        • 2018-06-02
        • 2018-09-23
        • 2022-11-10
        • 2020-09-27
        • 1970-01-01
        • 1970-01-01
        • 2015-03-03
        相关资源
        最近更新 更多