Configure & Open a Realm - Kotlin SDK
On this page
This page describes realm files and how to configure, open, and close a realm that only persists data locally. To open a realm that synchronizes data with Atlas using Device Sync, refer to Open a Synced Realm.
A realm is the core data structure used to organize data in Realm. Each realm is a collection of Realm objects: the objects that you use in your application as well as additional metadata that describe those objects. Each Realm object type has an object schema based on your defined object model.
A realm schema is a list of the valid object schemas that a realm may contain. You specify the schema when you open the realm. If a realm already contains data when you open it, Realm validates each object to ensure that an object schema was provided for its type and that it meets all of the constraints specified in the schema.
Realm Files
Realm stores a binary-encoded version of every object and type in a realm
in a single .realm
file. When you open a realm, Realm creates the
.realm
file if it doesn't already exist. The file is located at a specific
path, which you can define when you open the realm.
Tip
Work with Realm Files in Realm Studio
You can open, view, and edit the contents of realm files with Realm Studio.
If you don't want to create a .realm
file or its associated auxiliary
files, you can open an in-memory realm.
Refer to the Open an In-Memory Realm section for
more information.
Auxiliary Files
Realm creates additional files for each realm:
realm files, suffixed with "realm", e.g.
default.realm
: contain object data.lock files, suffixed with "lock", e.g.
default.realm.lock
: keep track of which versions of data in a realm are actively in use. This prevents realm from reclaiming storage space that is still used by a client application.note files, suffixed with "note", e.g.
default.realm.note
: enable inter-thread and inter-process notifications.management files, suffixed with "management", e.g.
default.realm.management
: internal state management.
Deleting these files has important implications.
For more information about deleting .realm
or auxiliary files, see:
Delete a Realm.
Open a Realm
To open a realm, create a RealmConfiguration
object that defines the details of a realm. Then, pass the resulting
RealmConfiguration
to Realm.open().
You can open a realm with default configuration values or you can build a
RealmConfiguration
with additional configuration options. However, you
must pass a schema
parameter that includes all object classes
that you want to use in the realm.
After you open the realm with the desired configuration, you can read and write data based on your defined schema.
The examples on this page refer to the following Realm objects:
class Frog : RealmObject { var _id: ObjectId = ObjectId() var name: String = "" } class Person : RealmObject { var _id: ObjectId = ObjectId() var name: String = "" }
Open a Default Realm
To open a realm with default configuration values, use the
RealmConfiguration.create().
method. You only need to define a set of object classes as the realm schema.
Then, pass the RealmConfiguration
to Realm.open().
The following example opens a default.realm
file at the default path with
a schema that includes the Frog
and Person
classes:
// Creates a realm with default configuration values val config = RealmConfiguration.create( // Pass object classes for the realm schema schema = setOf(Frog::class, Person::class) ) // Open the realm with the configuration object val realm = Realm.open(config) Log.v("Successfully opened realm: ${realm.configuration.name}") // ... use the open realm ...
Default File Location
If you don't define a directory for the realm file, the default app storage location for the platform is used. You can find the default directory for your platform with the following:
Android:
Context.getFiles()
JVM:
System.getProperty("user.dir")
macOS:
platform.Foundation.NSFileManager.defaultManager.currentDirectoryPath
iOS:
NSFileManager.defaultManager.URLForDirectory( NSDocumentDirectory, NSUserDomainMask, null, true, null )
Open an In-Memory Realm
You can open a realm entirely in memory, which does not create a
.realm
file or its associated auxiliary files. Instead, the SDK stores
objects in memory while the realm is open, and then discards the data
when all instances are closed.
To open a realm that runs without being written to a file, build a
RealmConfiguration
with the
RealmConfiguration.Builder
using the inMemory
property.
Then, pass the resulting RealmConfiguration
to Realm.open():
// Create the in-memory realm configuration val config = RealmConfiguration.Builder( schema = setOf(Frog::class, Person::class) ) .inMemory() .build() // Open the realm with the configuration object val realm = Realm.open(config) Log.v("Successfully opened an in-memory realm") // ... use the open realm ...
Note
In-Memory Realms are Not Persisted
Because in-memory realms are not persisted, ensure you have at least one open instance of the realm for as long as you want to access the data. After you close the last instance of an in-memory realm, the data is no longer available.
Customize a Realm Configuration
You can add optional arguments to the RealmConfiguration
to control the
specifics of the realm that you would like to open, including:
Defining a custom file name and file path
Passing an encryption key to encrypt a realm
Compacting a realm to reduce its file size
Specifying a schema version or migration block when making schema changes
Flagging whether Realm should delete the realm file if a migration is required
For more information on specific configuration implementations, refer to Manage Realm Files - Kotlin SDK.
To configure a realm with non-default values, create the RealmConfiguration
through RealmConfiguration.Builder.build()
and pass any properties you want to set. Then, pass the resulting
RealmConfiguration
to Realm.open().
In the following example, the RealmConfiguration
specifies a custom
name and directory ("my-directory-path/myRealmName.realm") and encryption key:
// Create a realm configuration with configuration builder // and pass all optional arguments val config = RealmConfiguration.Builder( schema = setOf(Frog::class, Person::class) ) .name("myRealmName.realm") .directory("my-directory-path") .encryptionKey(myEncryptionKey) .build() // Open the realm with the configuration object val realm = Realm.open(config) Log.v("Successfully opened realm: ${realm.configuration.name}") // ... use the open realm ...
Add Initial Data to Realm
You can add initial data to a realm by using an initialDataCallback. The callback is triggered when the realm is opened for the first time.
val config = RealmConfiguration.Builder( schema = setOf(Frog::class, Person::class) ) .initialData { copyToRealm(Frog().apply { name = "Kermit" }) copyToRealm(Person().apply { name = "Jim Henson" }) } .build() val realm = Realm.open(config) Log.v("Successfully opened realm: ${realm.configuration.name}") // Opened realm includes the initial data val initialFrog = realm.query<Frog>().find().first() val initialPerson = realm.query<Person>().find().first() Log.v("Realm initialized with: ${initialFrog.name} and ${initialPerson.name}")
Find a Realm File Path
To find the file path for a .realm
file, use the realm.configuration.path property:
val realmPath = realm.configuration.path Log.v("Realm path: $realmPath")
Close a Realm
You close a realm with realm.close(). This method blocks until all write transactions on the realm have completed.
realm.close()
Warning
Close Realms to Prevent Memory Leaks
It's important to close your realm instance to free resources. Failing to close
realms can lead to an OutOfMemoryError
.
Copy Data into a New Realm
To copy data from an existing realm to a new realm with different configuration options, pass the new configuration to the Realm.writeCopyTo() method. For example, you might copy data as a way to backup a local realm or to convert a synced realm to a local realm.
You can copy data to a realm that uses the same configuration:
Local realm to local realm
In-memory realm to in-memory realm
Synced realm to synced realm
You can copy data to a realm that uses different sync configurations:
Local realm to Partition-Based Sync realm
Synced realm to local realm
Synced realm to a synced realm for a different user
Warning
You cannot copy data from a local realm to a Flexible Sync realm. You cannot copy between different sync configuration types, for example Partition-Based Sync to Flexible Sync.
You can also combine changes to the configuration. For example, you can copy data from an unencrypted, in-memory synced realm to an encrypted local realm.
Some additional considerations to keep in mind while using
Realm.writeCopyTo()
:
The destination file cannot already exist.
Copying a realm is not allowed within a write transaction or during a migration.
When using Device Sync, you must sync all local changes with the server before the copy is written. This ensures that the file can be used as a starting point for a newly installed application. Realm throws an error if there are pending uploads.
You can use uploadAllLocalChanges() and downloadAllServerChanges() to ensure all sync processes are completed.
Example
Copy Data from Flexible Sync Realm to Local Realm
// Instantiate the synced realm with your App ID val app = App.create(YOUR_APP_ID) runBlocking { val user = app.login(credentials) // Create the synced realm configuration val syncConfig = SyncConfiguration.Builder(user, setOf(Frog::class)) .initialSubscriptions { realm -> add(realm.query<Frog>(),"all-frogs") } .build() // Open the synced realm and add data to it val syncRealm = Realm.open(syncConfig) Log.v("Successfully opened realm: ${syncRealm.configuration.name}") syncRealm.write { this.copyToRealm(Frog().apply { name = "Kermit" }) } // Wait for write to sync syncRealm.syncSession.uploadAllLocalChanges(30.seconds) // Create the local realm val localConfig = RealmConfiguration.Builder(setOf(Frog::class)) .name("local.realm") .build() // Copy data from synced realm to the new realm syncRealm.writeCopyTo(localConfig) // Close the synced realm when you're done copying syncRealm.close() // Open the new local realm val localRealm = Realm.open(localConfig) // Copied Frog object is available in the new realm val frog = localRealm.query<Frog>().find().first() Log.v("Copied Frog: ${frog.name}") localRealm.close() }
You can also include a new encryption key in the copied realm's configuration or remove the encryption key from the new configuration.
Example
Copy Data from Unencrypted to Encrypted Realm
runBlocking { // Create the unencrypted realm val unencryptedConfig = RealmConfiguration.Builder(setOf(Frog::class)) .name("unencrypted.realm") .build() // Open the realm and add data to it val unencryptedRealm = Realm.open(unencryptedConfig) unencryptedRealm.write { this.copyToRealm(Frog().apply { name = "Kermit" }) } // ... Generate encryption key ... // Create the encrypted realm val encryptedConfig = RealmConfiguration.Builder(setOf(Frog::class)) .name("encrypted.realm") .encryptionKey(encryptionKey) .build() // Copy data from `unencryptedRealm` to the new realm // Data is encrypted as part of the copy process unencryptedRealm.writeCopyTo(encryptedConfig) // Close the original realm when you're done copying unencryptedRealm.close() // Open the new encrypted realm val encryptedRealm = Realm.open(encryptedConfig) // Copied Frog object is available in the new realm val frog = encryptedRealm.query<Frog>().find().first() Log.v("Copied Frog: ${frog.name}") encryptedRealm.close() }
Example
Copy Data from In-Memory to Local Realm
runBlocking { // Create the in-memory realm val inMemoryConfig = RealmConfiguration.Builder(setOf(Frog::class)) .name("inMemory.realm") .inMemory() .build() // Open the realm and add data to it val inMemoryRealm = Realm.open(inMemoryConfig) inMemoryRealm.write { this.copyToRealm(Frog().apply { name = "Kermit" }) } // Create the local realm val localConfig = RealmConfiguration.Builder(setOf(Frog::class)) .name("local.realm") .build() // Copy data from `inMemoryRealm` to the new realm inMemoryRealm.writeCopyTo(localConfig) // Close the original realm when you're done copying inMemoryRealm.close() // Open the new local realm val localRealm = Realm.open(localConfig) // Copied Frog object is available in the new realm val frog = localRealm.query<Frog>().find().first() Log.v("Copied Frog: ${frog.name}") localRealm.close() }