Skip to content

Commit

Permalink
migrating to room
Browse files Browse the repository at this point in the history
  • Loading branch information
joreilly committed Sep 14, 2024
1 parent fdff6f9 commit af53eb1
Show file tree
Hide file tree
Showing 13 changed files with 155 additions and 93 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ import dev.johnoreilly.common.di.create

class BikeShareApplication : Application() {
val component: AndroidApplicationComponent by lazy {
AndroidApplicationComponent.create()
}

override fun onCreate() {
super.onCreate()
AndroidApplicationComponent.create(this)
}
}
8 changes: 0 additions & 8 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,3 @@ plugins {
alias(libs.plugins.kotlin.parcelize) apply false
}

// Explicitly adding the plugin to the classpath as it makes it easier to control the version
// centrally (don't need version in the 'plugins' block). Further, snapshots are not published with
// marker interface so would need to be added to the classpath manually anyway.
buildscript {
dependencies {
classpath(libs.realm.plugin)
}
}
24 changes: 13 additions & 11 deletions common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType

plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.android.library)
alias(libs.plugins.kotlinx.serialization)
alias(libs.plugins.kotlin.parcelize)
alias(libs.plugins.ksp)
alias(libs.plugins.kmpNativeCoroutines)
alias(libs.plugins.room)
alias(libs.plugins.jetbrainsCompose)
alias(libs.plugins.compose.compiler)
//alias(libs.plugins.realm.kotlin)
id(libs.plugins.realm.kotlin.get().pluginId)
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.parcelize)
id("io.github.luca992.multiplatform-swiftpackage") version "2.2.3"
}

Expand Down Expand Up @@ -52,7 +51,9 @@ kotlin {
api(libs.circuit.foundation)

implementation(libs.bundles.ktor.common)
implementation(libs.realm)
implementation(libs.androidx.room.runtime)
implementation(libs.sqlite.bundled)

api(libs.kmpObservableViewModel)

implementation(compose.ui)
Expand Down Expand Up @@ -117,19 +118,20 @@ tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach
kotlin.sourceSets.all {
languageSettings.optIn("kotlinx.cinterop.ExperimentalForeignApi")
languageSettings.optIn("kotlin.experimental.ExperimentalObjCName")
languageSettings.enableLanguageFeature("ExplicitBackingFields")
//languageSettings.enableLanguageFeature("ExplicitBackingFields")
}

ksp {
arg("me.tatarka.inject.generateCompanionExtensions", "true")
}


dependencies {
add("kspAndroid", libs.kotlininject.compiler)
add("kspIosX64", libs.kotlininject.compiler)
add("kspIosArm64", libs.kotlininject.compiler)
add("kspIosSimulatorArm64", libs.kotlininject.compiler)
add("kspJvm", libs.kotlininject.compiler)
ksp(libs.androidx.room.compiler)
ksp(libs.kotlininject.compiler)
}

room {
schemaDirectory("$projectDir/schemas")
}

Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package dev.johnoreilly.common.di

import android.app.Application
import android.content.Context
import androidx.room.Room
import androidx.sqlite.driver.bundled.BundledSQLiteDriver
import com.slack.circuit.foundation.Circuit
import dev.johnoreilly.common.database.AppDatabase
import dev.johnoreilly.common.database.dbFileName
import dev.johnoreilly.common.screens.CountryListPresenter
import dev.johnoreilly.common.screens.CountryListScreen
import dev.johnoreilly.common.screens.NetworkListPresenter
Expand All @@ -12,13 +18,14 @@ import dev.johnoreilly.common.ui.CountryListUi
import dev.johnoreilly.common.ui.NetworkListUi
import dev.johnoreilly.common.ui.StationListUI
import io.ktor.client.engine.android.Android
import kotlinx.coroutines.Dispatchers
import me.tatarka.inject.annotations.Component
import me.tatarka.inject.annotations.Provides


@Component
@Singleton
abstract class AndroidApplicationComponent: SharedApplicationComponent {
abstract class AndroidApplicationComponent(val application: Application): SharedApplicationComponent {

abstract val bikeShareContent: BikeShareContent

Expand All @@ -34,5 +41,15 @@ abstract class AndroidApplicationComponent: SharedApplicationComponent {

override fun getHttpClientEngine() = Android.create()

override fun getRoomDatabase() = createRoomDatabase(application)

companion object
}

fun createRoomDatabase(ctx: Context): AppDatabase {
val dbFile = ctx.getDatabasePath(dbFileName)
return Room.databaseBuilder<AppDatabase>(ctx, dbFile.absolutePath)
.setDriver(BundledSQLiteDriver())
.setQueryCoroutineContext(Dispatchers.IO)
.build()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package dev.johnoreilly.common.database

import androidx.room.*
import dev.johnoreilly.common.model.Network

internal expect object AppDatabaseCtor : RoomDatabaseConstructor<AppDatabase>

@Database(entities = [Network::class], version = 1)
@ConstructedBy(AppDatabaseCtor::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun bikeShareDao(): BikeShareDao
}

internal const val dbFileName = "bikeshare.db"

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package dev.johnoreilly.common.database

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import dev.johnoreilly.common.model.Network
import kotlinx.coroutines.flow.Flow

@Dao
interface BikeShareDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertNetworkList(networkList: List<Network>)

@Query("SELECT * FROM Network")
fun getNetworkListAsFlow(): Flow<List<Network>>
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package dev.johnoreilly.common.di

import dev.johnoreilly.common.database.AppDatabase
import dev.johnoreilly.common.remote.CityBikesApi
import dev.johnoreilly.common.repository.CityBikesRepository
import dev.johnoreilly.common.repository.NetworkDb
import dev.johnoreilly.common.viewmodel.CountriesViewModelShared
import dev.johnoreilly.common.viewmodel.NetworksViewModelShared
import dev.johnoreilly.common.viewmodel.StationsViewModelShared
Expand All @@ -14,8 +14,6 @@ import io.ktor.client.plugins.logging.LogLevel
import io.ktor.client.plugins.logging.Logger
import io.ktor.client.plugins.logging.Logging
import io.ktor.serialization.kotlinx.json.json
import io.realm.kotlin.Realm
import io.realm.kotlin.RealmConfiguration
import kotlinx.serialization.json.Json
import me.tatarka.inject.annotations.Provides
import me.tatarka.inject.annotations.Scope
Expand All @@ -40,15 +38,13 @@ interface SharedApplicationComponent {
val json: Json
@Provides get() = Json { isLenient = true; ignoreUnknownKeys = true; useAlternativeNames = false }

val realm: Realm
@Provides get() {
val config = RealmConfiguration.create(schema = setOf(NetworkDb::class))
return Realm.open(config)
}

@Provides
fun getHttpClientEngine(): HttpClientEngine

@Provides
fun getRoomDatabase(): AppDatabase


@Provides
fun httpClient(): HttpClient = createHttpClient(getHttpClientEngine(), json)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package dev.johnoreilly.common.model

import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity
data class Network(
val id: String,
@PrimaryKey val id: String,
val name: String,
val city: String,
val country: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,17 @@
package dev.johnoreilly.common.repository

import dev.johnoreilly.common.database.AppDatabase
import dev.johnoreilly.common.di.Singleton
import dev.johnoreilly.common.model.Network
import dev.johnoreilly.common.remote.CityBikesApi
import dev.johnoreilly.common.remote.Station
import io.realm.kotlin.Realm
import io.realm.kotlin.UpdatePolicy
import io.realm.kotlin.ext.query
import io.realm.kotlin.query.RealmResults
import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.annotations.PrimaryKey
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import me.tatarka.inject.annotations.Inject



class NetworkDb: RealmObject {
@PrimaryKey
var id: String = ""
var name: String = ""
var city: String = ""
var country: String = ""
var latitude: Double = 0.0
var longitude: Double = 0.0
}


@Inject @Singleton
class CityBikesRepository(val cityBikesApi: CityBikesApi,val realm: Realm) {
class CityBikesRepository(val cityBikesApi: CityBikesApi,val database: AppDatabase) {
private val mainScope: CoroutineScope = MainScope()

// val groupedNetworkList: StateFlow<Map<String,List<Network>>>
Expand All @@ -43,15 +26,14 @@ class CityBikesRepository(val cityBikesApi: CityBikesApi,val realm: Realm) {
init {
mainScope.launch {
launch {
realm.query<NetworkDb>().asFlow()
.map { it.list }
.collect { it: RealmResults<NetworkDb> ->
_networkList.value = it.toList().map {
Network(it.id, it.name, it.city, it.country, it.latitude, it.longitude)
database.bikeShareDao().getNetworkListAsFlow()
.collect {
_networkList.value = it.map {
Network(it.id, it.name, it.city, it.country, it.latitude, it.longitude)
}
_groupedNetworkList.value =
_networkList.value.groupBy { it.country }
}
_groupedNetworkList.value =
_networkList.value.groupBy { it.country }
}
}

fetchAndStoreNetworkList()
Expand All @@ -63,18 +45,10 @@ class CityBikesRepository(val cityBikesApi: CityBikesApi,val realm: Realm) {
val networkList = cityBikesApi.fetchNetworkList().networks
println(networkList)

realm.write {
networkList.forEach { networkDto ->
copyToRealm(NetworkDb().apply {
id = networkDto.id
name = networkDto.name
city = networkDto.location.city
country = networkDto.location.country
latitude = networkDto.location.latitude
longitude = networkDto.location.longitude
}, updatePolicy = UpdatePolicy.ALL)
}
}
database.bikeShareDao().insertNetworkList(networkList.map {
Network(it.id, it.name, it.location.city,
it.location.country, it.location.latitude, it.location.longitude)
})
} catch (e: Exception) {
// TODO report error up to UI
println("Exception during fetchAndStorePeople: $e")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
package dev.johnoreilly.common.di

import androidx.room.Room
import androidx.sqlite.driver.bundled.BundledSQLiteDriver
import dev.johnoreilly.common.database.AppDatabase
import dev.johnoreilly.common.database.dbFileName
import io.ktor.client.engine.darwin.Darwin
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import me.tatarka.inject.annotations.Component
import platform.Foundation.NSDocumentDirectory
import platform.Foundation.NSFileManager
import platform.Foundation.NSURL
import platform.Foundation.NSUserDomainMask


@Component
Expand All @@ -10,5 +20,26 @@ abstract class IosApplicationComponent: SharedApplicationComponent {

override fun getHttpClientEngine() = Darwin.create()

override fun getRoomDatabase() = createRoomDatabase()

companion object
}

fun createRoomDatabase(): AppDatabase {
val dbFile = "${fileDirectory()}/$dbFileName"
return Room.databaseBuilder<AppDatabase>(name = dbFile)
.setDriver(BundledSQLiteDriver())
.setQueryCoroutineContext(Dispatchers.IO)
.build()
}

private fun fileDirectory(): String {
val documentDirectory: NSURL? = NSFileManager.defaultManager.URLForDirectory(
directory = NSDocumentDirectory,
inDomain = NSUserDomainMask,
appropriateForURL = null,
create = false,
error = null,
)
return requireNotNull(documentDirectory).path!!
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
package dev.johnoreilly.common.di

import androidx.room.Room
import androidx.sqlite.driver.bundled.BundledSQLiteDriver
import dev.johnoreilly.common.database.AppDatabase
import dev.johnoreilly.common.database.dbFileName
import io.ktor.client.engine.java.Java
import me.tatarka.inject.annotations.Component
import java.io.File

@Component
@Singleton
abstract class DesktopApplicationComponent: SharedApplicationComponent {

override fun getHttpClientEngine() = Java.create()

override fun getRoomDatabase() = createRoomDatabase()

companion object
}

fun createRoomDatabase(): AppDatabase {
val dbFile = File(System.getProperty("java.io.tmpdir"), dbFileName)
return Room.databaseBuilder<AppDatabase>(name = dbFile.absolutePath,)
.setDriver(BundledSQLiteDriver())
.build()
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
org.gradle.jvmargs=-Xmx1536m
org.gradle.jvmargs=-Xmx4096m
android.useAndroidX=true
android.enableJetifier=false
kotlin.code.style=official
Expand Down
Loading

0 comments on commit af53eb1

Please sign in to comment.