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

Posted

技术标签:

【中文标题】Room - 模式导出目录未提供给注释处理器,因此我们无法导出模式【英文标题】:Room - Schema export directory is not provided to the annotation processor so we cannot export the schema 【发布时间】:2017-11-03 11:11:56 【问题描述】:

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

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

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

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

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

【问题讨论】:

【参考方案1】:

根据docs:

您可以设置注释处理器参数 (room.schemaLocation) 来告诉 Room 将架构导出到文件夹中。尽管这不是强制性的,但在您的代码库中包含版本历史记录是一种很好的做法,您应该将该文件提交到您的版本控制系统中(但不要将它与您的应用一起发布!)。

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

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

如果您关注下面的@mikejonesguy answer,您将遵循文档中提到的良好做法:)。 基本上你会在你的../app/schemas/ 文件夹中得到一个.json 文件。 它看起来像这样:


  "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\")"
    ]
  

如果我的理解是正确的,你会在每次数据库版本更新时得到这样一个文件,这样你就可以轻松地跟踪你的数据库的历史。

【讨论】:

“不要随您的应用一起发布”的真正含义是什么?它将包含在 APK 中吗? 如果遵循“不随您的应用发布”,我应该在生成 APK 之前删除 JSON 文件吗? “不随您的应用一起发布”是指“不要将 schemaLocation 设置为类似于 'app/res/raw'。将 schemaLocation 设置为未包含在 APK 中的目录。” @galcyurio $projectDir/schemas 是 APK 之外的目录,对吧?我已经探索了生成的 APK,但我在那里看不到它。虽然我看到了 /res (它占 app/src/main/res 的例子)。 @xarlymg89 您能否确认$projectDir/schemas 包含在 APK 中?根据this answer,自定义子目录不是。【参考方案2】:

在您的应用模块的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)



// ...

【讨论】:

如果有人想知道,这种确切的方法在使用 kapt 时也适用于 Kotlin 我们是否应该gitignore这个操作在app/schemas目录下生成的json文件。而且我听说我们应该将架构放入不包含在apk 中的目录中。我们该怎么做? @ravi 生成的架构文件应存储在版本控制中,因为 Room 使用它来检测更改并帮助确保数据库是否更改,您更新数据库版本并创建迁移计划 使用arguument +=,这样它就不会与您的 DI 库(如 Hilt)混淆。(有关更多信息,请参阅此答案***.com/a/62891182/5780236) @ChantellOsejo 刚刚更新。将“arguments = ...”更改为“arguments += ...”。【参考方案3】:

科特林?我们开始吧:

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 docs

【讨论】:

我得到了一个> No signature of method: build_xyz.android() is applicable for argument types: (build_xyz$_run_closure1) values: [build_xyz$_run_closure1@719007a9],其中xyz 是一个很长的随机字符串...这是一个错误吗? @MinhNghĩa,这里也一样。 This 可能是更好的选择 @mikejonesguy 上面的回答对我有用。 同样的问题,缺少签名方法。【参考方案4】:

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

因为“Schema导出目录没有提供给注解处理器”,所以我们需要提供schema导出的目录:

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

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

或者

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

(因为默认值始终为真)

步骤 [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:????)【参考方案5】:

@mikejonesguy answer 是完美的,以防万一您计划测试房间迁移(推荐),将架构位置添加到源集。

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

弗洛丽娜·蒙特内斯库 (source)

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

    // [...]

【讨论】:

【参考方案6】:

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

Unresolved reference: kapt

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

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

【讨论】:

也没有什么对我有用。我正在使用 Kotlin。 这个答案是如何工作的? arguments 是一个 MutableMap,val arguments: MutableMap<String, String>,当您尝试分配任何内容时会出现编译错误,并且添加 arguments["room.schemaLocation"] ="$projectDir/schemas" 对我不起作用。其他答案也不起作用。【参考方案7】:

可能你没有在@Database(entities = your_classes)子类RoomDatabase子类中添加你的房间类

【讨论】:

【参考方案8】:

如果您像我一样最近将某些课程移动到不同的包等。你使用安卓导航。确保将 argType 更改为与您的新包地址匹配。 来自:

app:argType="com.example.app.old.Item" 

到:

app:argType="com.example.app.new.Item" 

【讨论】:

以上是关于Room - 模式导出目录未提供给注释处理器,因此我们无法导出模式的主要内容,如果未能解决你的问题,请参考以下文章

以下选项未被任何处理器识别:'[kapt.kotlin.generated, room.incremental]'

Android Room 迁移未正确处理(错误的列顺序)

JSON 和处理未导出的字段

带有休眠注释的模式导出

索引处理程序未定义或未导出

dll导出函数参数可以是引用吗