Room: la directory di esportazione dello schema non viene fornita al processore delle annotazioni, quindi non è possibile esportare lo schema


349

Sto usando la stanza dei componenti del database Android

Ho configurato tutto, ma quando compilo, Android Studio mi dà questo avviso:

La directory di esportazione dello schema non viene fornita al processore delle annotazioni, quindi non è possibile esportare lo schema. È possibile fornire l' room.schemaLocationargomento del processore di annotazione O impostare exportSchema su false.

A quanto ho capito, è la posizione in cui si troverà il file DB

In che modo può influire sulla mia app? Qual è la migliore pratica qui? Devo usare la posizione ( falsevalore) predefinita ?

Risposte:


395

Secondo i documenti :

Puoi impostare l'argomento del processore di annotazione (room.schemaLocation) per dire a Room di esportare lo schema in una cartella. Anche se non è obbligatorio, è buona norma avere la cronologia delle versioni nella tua base di codice e dovresti eseguire il commit di quel file nel tuo sistema di controllo della versione (ma non spedirlo con la tua app!).

Quindi se non hai bisogno di controllare lo schema e vuoi sbarazzarti dell'avvertimento, aggiungi exportSchema = falseal tuo RoomDatabase, come segue.

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

Se segui la risposta @mikejonesguy di seguito, seguirai le buone pratiche menzionate nei documenti :). Fondamentalmente otterrai un .jsonfile nella tua ../app/schemas/cartella. E sembra qualcosa del genere:

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

Se la mia comprensione è corretta, otterrai tale file con ogni aggiornamento della versione del database, in modo da poter seguire facilmente la cronologia del tuo db.


7
Cosa significa veramente "Non spedire con la tua app"? Sarà incluso in APK?
Jongz Puangput

2
Se segui "Non spedire con la tua app", devo rimuovere i file JSON prima di generare APK?
illusionJJ

7
"Non spedire con la tua app" significa "Non impostare schemaLocation su" app / res / raw ". Impostare schemaLocation su una directory non inclusa nell'APK."
galcyurio,

3
@galcyurio $ projectDir / schemas è una directory fuori dall'APK, giusto? Ho esplorato l'APK generato e non lo vedo laggiù. Anche se vedo / res (quale account per app / src / main / res) per esempio.
xarlymg89,

1
@glucaio Ho esplorato l'APK (e anche il pacchetto App) e non l'ho trovato. Quindi credo che siamo al sicuro.
xarlymg89,

388

Nel build.gradlefile per il modulo dell'app, aggiungilo alla defaultConfigsezione (sotto la androidsezione). Questo scriverà lo schema in una schemassottocartella della cartella del progetto.

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

Come questo:

// ...

android {

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

    defaultConfig {

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

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

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

}

// ...

34
Se qualcuno si sta chiedendo, questo approccio esatto funziona anche per Kotlin quando si usa kapt
DanielDiSu,

1
Dovremmo gitignore il file json generato nella app/schemasdirectory da questa operazione. E ho sentito che dovremmo mettere lo schema in una directory che non è inclusa in apk. Come possiamo farlo?
ravi,

2
@ravi i file di schema generati devono essere archiviati nel controllo versione in quanto viene utilizzato da Room per rilevare le modifiche e aiutare a garantire che se il database cambia aggiorni la versione del database e crei un piano di migrazione
appmattus

1
Questa configurazione influisce sulla versione di rilascio? Voglio dire, quando esporto il progetto in un'app di rilascio.
Anargu,

Se questa soluzione genera ERRORE: impossibile trovare l'annotazione del metodo ProcessorOptions () per gli argomenti , controlla la risposta di Luna, di seguito: stackoverflow.com/a/54366985/1617737
ban-geoengineering

184

Kotlin? Eccoci qui:

android {

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

    defaultConfig {

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

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

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

//...

Non dimenticare il plug-in:

apply plugin: 'kotlin-kapt'

Per ulteriori informazioni sul processore di annotazioni di Kotlin , visitare: Documenti di Kotlin


Come il modo in cui hai risposto: D
theapache64

12

Le risposte sopra sono corrette. Questa versione è facile da seguire:

Perché "La directory di esportazione dello schema non è fornita al processore di annotazione", Quindi dobbiamo fornire la directory per l'esportazione dello schema:

Passaggio [1] Nel file che estende RoomDatabase, modificare la riga in:

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

O

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

(perché il valore predefinito è sempre true)

Passaggio [2] Nel tuo file build.gradle (project: ????), all'interno della defaultConfig {} (che si trova all'interno della sezione grande di Android {} ), aggiungi la sezione javaCompileOptions {} , sarà come:

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

$ projectDir : è un nome variabile, non è possibile modificarlo. otterrà la tua directory di progetto

schemi : è una stringa, puoi cambiarla come preferisci. Per esempio: "$projectDir/MyOwnSchemas".toString()


nel passaggio [2], sei sicuro che sia il build.gradle(project:????)e no build.gradle(app:????)?
Ace

9

La risposta di @mikejonesguy è perfetta, nel caso in cui si pianifichi di testare le migrazioni della stanza (consigliato), aggiungere la posizione dello schema ai set di sorgenti.

Nel file build.gradle si specifica una cartella per posizionare questi file JSON dello schema generati. Man mano che aggiorni lo schema, finirai con diversi file JSON, uno per ogni versione. Assicurati di eseguire il commit di ogni file generato nel controllo del codice sorgente. La prossima volta che aumenterai di nuovo il numero di versione, Room sarà in grado di utilizzare il file JSON per i test.

  • Florina Muntenescu ( fonte )

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

Uso i .ktsfile Gradle (Kotlin Gradle DSL) e il kotlin-kaptplug-in, ma ricevo ancora un errore di compilazione dello script quando utilizzo la risposta di Ivanov Maksim.

Unresolved reference: kapt

Per me questa è stata l'unica cosa che ha funzionato:

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

Niente funziona neanche per me. Sto usando Kotlin.
nyxee

0

Probabilmente non hai aggiunto la classe della tua classe alla RoomDatabaseclasse del bambino in@Database(entities = {your_classes})

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.