Room-未将模式导出目录提供给注释处理器,因此我们无法导出模式


348

我正在使用Android数据库组件室

我已经配置了所有内容,但是在编译时,Android Studio会向我发出以下警告:

模式导出目录未提供给注释处理器,因此我们无法导出模式。您可以提供room.schemaLocation注释处理器参数,也可以 将exportSchema设置为false。

据我了解,这是数据库文件所在的位置

它如何影响我的应用程序?最佳做法是什么?我应该使用默认位置(false值)吗?

Answers:


394

根据文档

您可以设置注释处理器参数(room.schemaLocation)来指示Room将架构导出到文件夹中。尽管不是强制性的,但在代码库中保留版本历史记录是一个好习惯,您应该将该文件提交到版本控制系统中(但不要随应用程序一起提供!)。

因此,如果您不需要检查架构并且想要摆脱警告,只需将添加exportSchema = falseRoomDatabase,如下所示。

@Database(entities = { YourEntity.class }, version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
   //...
}

如果您遵循以下@mikejonesguy 答案,则将遵循docs中提到的良好做法:)。基本上,您会.json../app/schemas/文件夹中找到一个文件。它看起来像这样:

{
  "formatVersion": 1,
  "database": {
    "version": 1,
    "identityHash": "53db508c5248423325bd5393a1c88c03",
    "entities": [
      {
        "tableName": "sms_table",
        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `message` TEXT, `date` INTEGER, `client_id` INTEGER)",
        "fields": [
          {
            "fieldPath": "id",
            "columnName": "id",
            "affinity": "INTEGER"
          },
          {
            "fieldPath": "message",
            "columnName": "message",
            "affinity": "TEXT"
          },
          {
            "fieldPath": "date",
            "columnName": "date",
            "affinity": "INTEGER"
          },
          {
            "fieldPath": "clientId",
            "columnName": "client_id",
            "affinity": "INTEGER"
          }
        ],
        "primaryKey": {
          "columnNames": [
            "id"
          ],
          "autoGenerate": true
        },
        "indices": [],
        "foreignKeys": []
      }
    ],
    "setupQueries": [
      "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"53db508c5248423325bd5393a1c88c03\")"
    ]
  }
}

如果我的理解是正确的,那么每次数据库版本更新时,您都会获得一个这样的文件,以便您可以轻松地跟踪数据库的历史记录。


7
“不随您的应用一起提供”的真正含义是什么?它将包含在APK中吗?
Jongz Puangput

2
如果遵循“不随您的应用一起提供”,我应该在生成APK之前删除JSON文件吗?
illusionJJ

7
“不随您的应用一起提供”是指“请勿将schemaLocation设置为类似于“ app / res / raw”。将schemaLocation设置为APK中未包含的目录。”
galcyurio

3
@galcyurio $ projectDir / schemas是APK之外的目录,对吗?我已经浏览了生成的APK,但在那边看不到它。虽然我看到例如/ res(占app / src / main / res)。
xarlymg89

1
@glucaio我浏览了APK(以及App捆绑包),但没有找到。所以我相信我们很安全。
xarlymg89

387

build.gradle您的应用模块文件中,将其添加到defaultConfig部分(在该android部分下)。这会将架构写到schemas项目文件夹的子文件夹中。

javaCompileOptions {
    annotationProcessorOptions {
        arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
    }
}

像这样:

// ...

android {

    // ... (compileSdkVersion, buildToolsVersion, etc)

    defaultConfig {

        // ... (applicationId, miSdkVersion, etc)

        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }
    }

    // ... (buildTypes, compileOptions, etc)

}

// ...

34
如果有人想知道,当使用kapt
DanielDiSu

1
我们是否应该忽略app/schemas此操作在目录中生成的json文件。我听说我们应该将架构放入目录中未包含的目录中apk。我们该怎么做?
拉维

2
@ravi应当将生成的模式文件存储在版本控制中,因为Room可以使用该文件来检测更改并帮助确保数据库是否更改,您可以更新数据库版本并创建迁移计划
appmattus

1
此配置是否影响发行版本?我的意思是,当我将项目导出到发布应用程序时。
Anargu

如果该解决方案导致错误:找不到参数的方法AnnotationProcessorOptions(),请查看以下Luna的答案:stackoverflow.com/a/54366985/1617737
ban-geoengineering

184

科特林?开始了:

android {

    // ... (compileSdkVersion, buildToolsVersion, etc)

    defaultConfig {

        // ... (applicationId, miSdkVersion, etc)

        kapt {
            arguments {
                arg("room.schemaLocation", "$projectDir/schemas")
            }
        }
    }

    buildTypes {
        // ... (buildTypes, compileOptions, etc)
    }
}

//...

不要忘记插件:

apply plugin: 'kotlin-kapt'

有关kotlin注释处理器的更多信息,请访问: Kotlin文档


就像您回答它的方式一样:D
theapache64

12

以上答案是正确的。这个版本很容易理解:

由于“未将模式导出目录提供给注释处理器”,因此我们需要提供用于模式导出的目录:

步骤[1]在扩展RoomDatabase的文件中,将行更改为:

`@Database(entities = ???.class,version = 1, exportSchema = true)`

要么

`@Database(entities = ???.class,version = 1)` 

(因为默认值始终为true)

步骤[2]在您的build.gradle(project:????)文件中,在defaultConfig {}内部(在android {}大内部),添加javaCompileOptions {}部分,如下所示:

         android{
                defaultConfig{
                      //javaComplieOptions SECTION
                      javaCompileOptions {
                            annotationProcessorOptions {
                                     arguments = ["room.schemaLocation":"$projectDir/schemas".toString()]
                            }
                       }
                      //Other SECTION
                      ...
                }
         }

$ projectDir:是变量名,您不能更改它。它将获得您自己的项目目录

schemas:是一个字符串,您可以将其更改为任意字符串。例如: "$projectDir/MyOwnSchemas".toString()


在步骤[2]中,确定是build.gradle(project:????)而不是build.gradle(app:????)
Ace

9

@mikejonesguy的答案很完美,以防万一,您打算测试房间迁移(推荐),请将架构位置添加到源集中。

在build.gradle文件中,指定一个文件夹来放置这些生成的模式JSON文件。在更新架构时,最终会得到几个JSON文件,每个版本一个。确保将每个生成的文件提交到源代码管理。下次再次增加版本号时,Room将能够使用JSON文件进行测试。

  • Florina Muntenescu(来源

build.gradle

android {

    // [...]

    defaultConfig {

        // [...]

        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }
    }

    // add the schema location to the source sets
    // used by Room, to test migrations
    sourceSets {
        androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
    }

    // [...]
}

3

我使用.ktsGradle文件(Kotlin Gradle DSL)和kotlin-kapt插件,但是当我使用Ivanov Maksim的答案时,仍然收到脚本编译错误。

Unresolved reference: kapt

对我来说,这是唯一有效的方法:

android {
    defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = mapOf("room.schemaLocation" to "$projectDir/schemas")
            }
        }
    }
}

没什么对我有用。我正在使用Kotlin。
nyxee

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.