Комната - каталог экспорта схемы не предоставлен обработчику аннотаций, поэтому мы не можем экспортировать схему

Я использую компонентную базу данных Android

Я все настроил, но при компиляции Android Studio выдает мне следующее предупреждение:

Каталог экспорта схемы не предоставляется обработчику аннотаций, поэтому мы не можем экспортировать схему. Вы можете предоставить room.schemaLocation аргумент процессора аннотации ИЛИ установите для exportSchema значение false.

Как я понимаю, это место, где будет расположен файл БД

Как это может повлиять на мое приложение? Какова лучшая практика здесь? Должен ли я использовать местоположение по умолчанию (false значение)?

14 ответов

Решение

Согласно документам:

Вы можете установить аргумент процессора аннотаций (room.schemaLocation), чтобы сообщить Room об экспорте схемы в папку. Несмотря на то, что это не является обязательным, рекомендуется иметь историю версий в вашей кодовой базе, и вы должны зафиксировать этот файл в вашей системе контроля версий (но не поставляйте его вместе с приложением!).

Так что если вам не нужно проверять схему и вы хотите избавиться от предупреждения, просто добавьте exportSchema = false на ваш RoomDatabase, следующее.

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

Если вы будете следовать ответу @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\")"
    ]
  }
}

Если мое понимание верно, вы будете получать такой файл при каждом обновлении версии базы данных, чтобы вы могли легко следить за историей вашей базы данных.

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

}

// ...

Котлин? Вот так:

android {

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

    defaultConfig {

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

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

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

//...

Не забудьте о плагине:

apply plugin: 'kotlin-kapt'

Для получения дополнительной информации о процессоре аннотаций kotlin, пожалуйста, посетите: Kotlin docs

Для Котлин КСП:

      ksp {
    arg('room.schemaLocation', "$projectDir/schemas")
}

Выше ответы верны. Эту версию легко понять:

Поскольку "Каталог экспорта схемы не предоставляется процессору аннотаций", поэтому нам нужно предоставить каталог для экспорта схемы:

Шаг [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: это имя переменной, вы не можете его изменить. он получит ваш собственный каталог проектов

схемы: это строка, вы можете изменить ее на любую, какую захотите. Например:"$projectDir/MyOwnSchemas".toString()

Ответ @mikejonesguy идеален, на случай, если вы планируете протестировать миграцию комнаты (рекомендуется), добавьте расположение схемы в исходные наборы.

В вашем файле build.gradle вы указываете папку для размещения этих сгенерированных файлов JSON схемы. При обновлении схемы у вас будет несколько файлов JSON, по одному для каждой версии. Убедитесь, что вы передаете каждый сгенерированный файл в систему контроля версий. В следующий раз, когда вы снова увеличите номер версии, Room сможет использовать файл JSON для тестирования.

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

    // [...]
}

Я использую .kts Файлы Gradle (Kotlin Gradle DSL) и kotlin-kapt плагин, но я все еще получаю ошибку компиляции скрипта, когда использую ответ Иванова Максима.

Unresolved reference: kapt

Для меня это было единственное, что сработало:

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

Просто публикую то, что сработало для меня, используя 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"
            }
        }
    }

Чтобы это работало, вам также необходимо установитьexportSchemaкtrue

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

    abstract val dao: ScoresDAO
}

Чтобы убедиться, что это работает, вы должны увидеть вновь созданный каталог схем в корневом каталоге модуля со следующей сборкой, как показано ниже.

Котлинский способ согласно официальному документу :

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

Если, как и я, вы недавно переместили определенные классы в разные пакеты и т. Д. а вы используете Android-навигацию. Обязательно измените argType, чтобы он соответствовал новому адресу пакета. из:

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

кому:

app:argType="com.example.app.new.Item" 
      // For javac or KAPT, configure using android DSL:
android {
  ...
  defaultConfig {
    javaCompileOptions {
      annotationProcessorOptions {
        compilerArgumentProviders(
          RoomSchemaArgProvider(File(projectDir, "schemas"))
        )
      }
    }
  }
}

// For KSP, configure using KSP extension:
ksp {
  arg(RoomSchemaArgProvider(File(projectDir, "schemas")))
}

Возможно, вы не добавили класс своей комнаты к ребенку RoomDatabase дочерний класс в @Database(entities = {your_classes})

Если вы используете комнату с ksp в сборке модуля, вам необходимо определить RoomSchemaArgProvider.

      class RoomSchemaArgProvider(
    @get:InputDirectory
    @get:PathSensitive(PathSensitivity.RELATIVE)
    val schemaDir: File
) : CommandLineArgumentProvider {

    override fun asArguments(): Iterable<String> {
        // Note: If you're using KSP, change the line below to return
         return listOf("room.schemaLocation=${schemaDir.path}")
//        return listOf("-Aroom.schemaLocation=${schemaDir.path}")
    }
}

android {


    // For KSP, configure using KSP extension:
    ksp {
        arg(RoomSchemaArgProvider(File(projectDir, "schemas")))
    }
}

А затем убедитесь, что у вас есть каталог в приложении/схемах. Не знаю, почему в моем случае он не был создан автоматически.

Другие вопросы по тегам