Quick Start - Kotlin SDK
On this page
This page contains information to quickly use Realm with the Kotlin SDK. The optional Add Device Sync section illustrates how to get Atlas Device Sync integrated into your application.
Before you begin, ensure you have installed the Kotlin SDK for your platform.
Note
Using this Quick Start with KMP
If you're running this project in a fresh Kotlin Multiplatform (KMP) template project, you can
copy and paste the following snippets into the Greeting.greeting()
method in the
commonMain
module.
Define Your Object Model
Your application's data model defines the structure of data stored within Realm. You can define your application's data model via Kotlin classes in your application code with Realm Object Models.
To define your application's data model, add a class definition to your application code. The example below illustrates the creation of an 'Item' model that represents Todo items in a Todo list app.
class Item() : RealmObject { var _id: ObjectId = ObjectId() var isComplete: Boolean = false var summary: String = "" var owner_id: String = "" constructor(ownerId: String = "") : this() { owner_id = ownerId } }
Open a Realm
Use RealmConfiguration.create() to open a realm using default parameters. Pass your configuration to the Realm factory constructor to generate an instance of that realm:
val config = RealmConfiguration.create(schema = setOf(Item::class)) val realm: Realm = Realm.open(config)
For more information on how to control the specifics of the RealmConfiguration you would like to open (e.g. name, location, schema version), refer to Open & Close a Realm.
Create, Read, Update, and Delete Objects
Once opened, you can create objects within a realm in a write transaction block.
To create a new Item
, instantiate an instance of the
Item
class and add it to the realm in a write transaction block:
realm.writeBlocking { copyToRealm(Item().apply { summary = "Do the laundry" isComplete = false }) }
You can retrieve a collection of all Todo items in the realm with query.find():
// all items in the realm val items: RealmResults<Item> = realm.query<Item>().find()
You can also filter a collection to retrieve a more specific collection of objects:
// items in the realm whose name begins with the letter 'D' val itemsThatBeginWIthD: RealmResults<Item> = realm.query<Item>("summary BEGINSWITH $0", "D") .find() // todo items that have not been completed yet val incompleteItems: RealmResults<Item> = realm.query<Item>("isComplete == false") .find()
Find more information about string Realm queries in Filter Data.
To modify a Todo item, update its properties in a write transaction block:
// change the first item with open status to complete to show that the todo item has been done realm.writeBlocking { findLatest(incompleteItems[0])?.isComplete = true }
Finally, you can delete a Todo item by calling mutableRealm.delete() in a write transaction block:
// delete the first item in the realm realm.writeBlocking { val writeTransactionItems = query<Item>().find() delete(writeTransactionItems.first()) }
Watch for Changes
You can watch a realm, collection, or object for changes with the observe
method.
Important
Serverless Limitations
You cannot watch for changes if the data source is an Atlas serverless instance. MongoDB serverless currently does not support change streams, which are used on watched collections to listen for changes.
In the following example, we listen for changes on all Item
objects.
// flow.collect() is blocking -- run it in a background context val job = CoroutineScope(Dispatchers.Default).launch { // create a Flow from the Item collection, then add a listener to the Flow val itemsFlow = items.asFlow() itemsFlow.collect { changes: ResultsChange<Item> -> when (changes) { // UpdatedResults means this change represents an update/insert/delete operation is UpdatedResults -> { changes.insertions // indexes of inserted objects changes.insertionRanges // ranges of inserted objects changes.changes // indexes of modified objects changes.changeRanges // ranges of modified objects changes.deletions // indexes of deleted objects changes.deletionRanges // ranges of deleted objects changes.list // the full collection of objects } else -> { // types other than UpdatedResults are not changes -- ignore them } } } }
Later, when you're done observing, cancel the job to cancel the coroutine:
job.cancel() // cancel the coroutine containing the listener
Close a Realm
To close a realm and all underlying resources, call realm.close(). The
close()
method blocks until all write transactions on the realm have
completed.
realm.close()
Add Device Sync (Optional)
This section illustrates how to authenticate with an Anonymous User, and open a Flexible Sync realm to begin syncing data between devices.
Prerequisites
The code snippets in this section require the following:
Enabled anonymous authentication in the App Services UI
Enable Flexible Sync with Development Mode toggled on and an
owner_id
field in the Queryable Fields section
Initialize the App
To use App Services features such as authentication and sync, access your App Services App using your App ID. You can find your App ID in the App Services UI.
val app = App.create(YOUR_APP_ID)
Authenticate a User
To authenticate and log in a user, call App.login. When anonymous authentication is enabled, users can immediately log into your app without providing any identifying information:
val credentials = Credentials.anonymous() val user = app.login(credentials)
Open a Synced Realm
Once you have initialized your Atlas App Services App, authenticated a user, and defined your object model, you can create a SyncConfiguration.
If you have opened a local realm following the Open a Realm section above, replace the
RealmConfiguration with
the SyncConfiguration
described below.
Pass the authenticated user and the Item
class to the SyncConfiguration.Builder
function to create a Flexible Sync Configuration.
Important
Initial Subscriptions
You need at least one subscription before you can read from or write to the realm. Use initialSubscriptions to define the initial subscription set when the Realm file is first opened. Pass the query you wish to subscribe to and a name for the subscription to the add() function.
The example below specifies a subscription named "User's Items" with
all Item
objects.
// create a SyncConfiguration val config = SyncConfiguration.Builder( user, setOf(Item::class) ) // the SyncConfiguration defaults to Flexible Sync, if a Partition is not specified .initialSubscriptions { realm -> add( realm.query<Item>( "owner_id == $0", // owner_id == the logged in user user.id ), "User's Items" ) } .build() val realm = Realm.open(config)
Next: Check out the Template Apps and Tutorial
Check out the template app to experiment with another quick way to start coding with the Realm Kotlin SDK. The
Kotlin SDK template, labeled android.kotlin.todo.flex
, is a premade
application that integrates Realm and Atlas Device Sync into a
customizable android app.
Alternatively, if you are interested in a guided experience, you can read our Android with Kotlin SDK tutorial that expands on the template app.