Room - Schema导出目录未提供给注释处理器,因此我们无法导出架构

Mis*_*pov 310 java database android android-room

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

我已经配置了所有内容,但是当我编译时,Android Studio会给我这个警告:

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

据我所知,它是DB文件所在的位置

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

Dor*_*ean 345

根据文档:

您可以设置注释处理器参数(room.schemaLocation)以告知Room将架构导出到文件夹中.即使它不是强制性的,最好在代码库中包含版本历史记录,然后将该文件提交到版本控制系统中(但不要随应用程序一起提供!).

因此,如果您不需要检查架构并且想要删除警告,只需添加exportSchema = false到您的RoomDatabase,如下所示.

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

如果您按照下面的@mikejonesguy 回答,您将遵循文档中提到的良好做法:).基本上你会.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\")"
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)

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

  • “不要随您的应用一起提供”意味着“不要将 schemaLocation 设置为喜欢 'app/res/raw'。将 schemaLocation 设置为未包含在 APK 中的目录。” (9认同)
  • 它的真正含义"请勿随应用一起发货"?它将包含在APK中? (5认同)
  • 如果按照"不随附您的应用程序",我应该在生成APK之前删除JSON文件吗? (2认同)
  • @galcyurio $ projectDir / schemas是APK之外的目录,对吗?我已经浏览了生成的APK,但在那边看不到它。虽然我看到例如/ res(占app / src / main / res)。 (2认同)
  • @xarlymg89 您是否能够确认 APK 中_不_包含“$projectDir/schemas”?根据[这个答案](/sf/answers/764917331/),自定义子目录不是。 (2认同)
  • @glucaio 我探索了 APK(以及应用程序包)但没有找到它。所以我相信我们是安全的。 (2认同)

mik*_*guy 335

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

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

像这样:

// ...

android {

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

    defaultConfig {

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

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

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

}

// ...
Run Code Online (Sandbox Code Playgroud)

  • 如果有人想知道,这个确切的方法也适用于Kotlin使用*kapt* (29认同)
  • @ravi 生成的架构文件应该存储在版本控制中,因为 Room 使用它来检测更改并帮助确保数据库是否更改您更新数据库版本并创建迁移计划 (5认同)
  • 使用 `arguument +=` 这样它就不会扰乱像 Hilt 这样的 DI 库。(有关更多信息,请参阅此答案 /sf/answers/4402382771/) (4认同)
  • 我们是否应该 gitignore 此操作在 `app/schemas` 目录中生成的 json 文件。我听说我们应该将模式放入一个不包含在“apk”中的目录中。我们怎样才能做到这一点? (2认同)
  • 这个配置对release版本有影响吗?我的意思是,当我将项目导出到发布应用程序时。 (2认同)
  • @ChantellOsejo 刚刚更新。将“参数 = ...”更改为“参数 += ...”。 (2认同)

Iva*_*sim 151

科特林?开始了:

android {

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

    defaultConfig {

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

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

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

//...
Run Code Online (Sandbox Code Playgroud)

不要忘记插件:

apply plugin: 'kotlin-kapt'

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

  • 我得到了一个`>没有方法签名:build_xyz.android()适用于参数类型:(build_xyz$_run_closure1)值:[build_xyz$_run_closure1@719007a9]`其中`xyz`是一个长随机字符串...是吗一个错误? (2认同)

Eyj*_*afl 80

对于 Kotlin KSP:

ksp {
    arg('room.schemaLocation', "$projectDir/schemas")
}
Run Code Online (Sandbox Code Playgroud)

(这是 Groovy DSL,在 Kotlin DSL 中使用双引号)

  • 您可以将其粘贴到“build.gradle (:app)”中任何您想要的位置。 (2认同)

小智 10

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

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

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

`@Database(entities = ???.class,version = 1, exportSchema = true)`
Run Code Online (Sandbox Code Playgroud)

要么

`@Database(entities = ???.class,version = 1)` 
Run Code Online (Sandbox Code Playgroud)

(因为默认值始终为true)

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

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

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

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


che*_*aby 7

@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())
    }

    // [...]
}
Run Code Online (Sandbox Code Playgroud)


Sag*_*yan 7

kapt {
  arguments {
    arg("room.schemaLocation", "$projectDir/schemas")
  }
}
Run Code Online (Sandbox Code Playgroud)


jsa*_*jsa 6

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

Unresolved reference: kapt
Run Code Online (Sandbox Code Playgroud)

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

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


Ali*_*rei 5

按照官方文档的Kotlin方式:

android {
...
defaultConfig {
    ...
    javaCompileOptions {
        annotationProcessorOptions {
            arguments += mapOf(
                "room.schemaLocation" to "$projectDir/schemas",
                "room.incremental" to "true",
                "room.expandProjection" to "true"
            )
        }
    }
}
}
Run Code Online (Sandbox Code Playgroud)


Fan*_*dez 5

只是发布对我有用的东西Kotlin DSL

defaultConfig {
        applicationId = ""
        minSdk = 26
        targetSdk = 33
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables.useSupportLibrary = true
        
        //add this in the build.gradle.kts(app) file
        javaCompileOptions {
            annotationProcessorOptions {
                arguments["room.schemaLocation"] =
                    "$projectDir/schemas"
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

为此,您还需要设置exportSchematrue

@Database(entities = [Entity::class], version = 1, exportSchema = true)
@TypeConverters(Converters::class)
abstract class ScoresDatabase : RoomDatabase() {

    abstract val dao: ScoresDAO
}
Run Code Online (Sandbox Code Playgroud)

为了确认它有效,您应该在下一个版本的模块根目录中看到新创建的schemas目录,如下所示。

在此输入图像描述