Using Kodein-DB NoSQL database in a Kotlin Multiplatform project

Share on:

A big factor in the increasing adoption of Kotlin Multiplatform is the ever growing number of KMP libraries that are becoming available. A new addition to this list, albeit in beta right now, is Kodein-DB, described as an “embedded NoSQL indexed document database for Android, iOS, and client JVM”. In this post I’m going to describe what was involved in adding initial use of Kodein-DB to BikeShare project.



Our model in this example is the following data class which was updated to implement Metadata. Note that Kodein-DB is compatible with Kotlinx Serialization library which we’re using already in this project in conjunction with Ktor for remote API requests.

@Serializable
data class Network(override val id: String, val name: String, val location: Location, 
	val stations: List<Station> = emptyList()) : Metadata


Following code is used to create the database (more on getApplicationFilesDirectoryPath() later).

db = DB.factory
    .inDir(getApplicationFilesDirectoryPath()) // expect fun getApplicationFilesDirectoryPath(): String
    .open("bikeshare_db", TypeTable {
        root<Network>()
    }, KotlinxSerializer()) // Using KotlinX Serializarion


And then, when app starts up, the following code is used to retrieve data (using Ktor) from remote endpoint and then stores the list of Network objects returned directly to the database.

private suspend fun fetchAndStoreNetworkList() {
    val networkList = cityBikesApi.fetchNetworkList().networks
    networkList.forEach {
        db.put(it)
    }
}


We then have following method, called from UI code, that returns list of networks.

fun fetchNetworkList() : List<Network> {
    return db.find<Network>().all().useModels { it.toList() }
}


Note use of getApplicationFilesDirectoryPath() when creating the db. This is an expect/actual function where, as shown below, actual platform specific implementations are provided for iOS and Android.

expect fun getApplicationFilesDirectoryPath(): String

iOS

actual fun getApplicationFilesDirectoryPath(): String =
    NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true)[0] as String

Android

actual fun getApplicationFilesDirectoryPath(): String =
    appContext.filesDir.absolutePath


The following are the Kodein-DB library dependencies that we added to gradle build file for common KMP shared module (current version is 0.3.0).

implementation ("org.kodein.db:kodein-db:${Versions.kodein_db}")
implementation ("org.kodein.db:kodein-db-serializer-kotlinx:${Versions.kodein_db}")


And this is what I have right now for the iOS client (using SwiftUI) consuming that fetchNetworkList() method above (that reads data from db).

iOS Network List Screen


And likewise on Android

Android Network List Screen


There are a number of additional capabilities provided by this library that we haven’t made use of yet including more complex querying and adding listener for db changes….some examples of those in this article. The changes made so far have been pushed to this branch of BikeShare repo.

Featured in Kotlin Weekly Issue #218

Purpose of providing this is primarily to help “close the loop” and provide way to post feedback/ask questions etc.