name: portada class: portada-slide, center, middle # Accés a BD ## Sqldelight --- # Llibreries accés a BD Kotlin - Room - SqlDelight (https://sqldelight.github.io/sqldelight/2.0.2/multiplatform_sqlite/) - ... --- # Sqlite - SQL database engine - Desktop: Fitxer - Android, Ios - Ràpid, petit i amb totes les funcionalitats --- # Plugin Intellij/Android Studio - https://plugins.jetbrains.com/plugin/8191-sqldelight --- # Configuració a Gradle ```kotlin plugins { id("app.cash.sqldelight") version "2.0.2" } kotlin { commonMain.dependencies{ implementation("app.cash.sqldelight:coroutines-extensions:2.0.2") } androidMain.dependencies { implementation("app.cash.sqldelight:android-driver:2.0.2") } nativeMain.dependencies { implementation("app.cash.sqldelight:native-driver:2.0.2") } jvmMain.dependencies { implementation("app.cash.sqldelight:sqlite-driver:2.0.2") } } ``` --- # Gradle ```kotlin sqldelight { databases { create("Database") { packageName.set("cat.itb.m78.exercices.db") schemaOutputDirectory.set(file("src/commonMain/sqldelight/databases")) verifyMigrations.set(true) } } } ``` --- # Definir esquema i queries src/commonMain/sqldelight/cat/itb/m78/exercices/db/myTable.sq ```sql CREATE TABLE myTable ( id INTEGER PRIMARY KEY NOT NULL, text TEXT NOT NULL ); CREATE INDEX myTable_full_name ON myTable(text); selectAll: SELECT * FROM myTable; insert: INSERT INTO myTable(text) VALUES (?); ``` --- # Generate files - Gradle : sqldelight:generateSqlDelightInterface - generateCommonMainMessagesDBSchema: Genera el fitxer 1.db --- # Driver factory A common: ``` expect fun createDriver(): SqlDriver fun createDatabase(): Database { val driver = createDriver() return Database(driver) } val database by lazy { createDatabase() } ``` --- # Driver factory JVM: - [DatabaseMigrationHelper.kt](DatabaseMigrationHelper.kt) ``` actual fun createDriver(): SqlDriver { val userHome = System.getProperty("user.home") val file = Path(userHome, "myDatabase.db") val driver = JdbcSqliteDriver("jdbc:sqlite:${file.absolutePathString()}") migrateIfNeeded(driver, Database.Schema) return driver } ``` --- # Queries ``` val myTableQueries = database.myTableQueries myTableQueries.insert("some Text") val all = myTableQueries.selectAll().executeAsList() val one = myTableQueries.find(1).executeAsOneOrNull() ``` --- # Queries ``` viewModelScope.launch { withContext(Dispatchers.Default){ database.myQueries.insert("some text") } // do after insert } ``` --- # Migrations - Si modifiques l'esquema de la BD hauràs de 1. O eliminar la BD de home (només durant el desenvolupament) 2. Crear migracions de la BD --- # Migracions - La tasca de gradle generateCommonMainDatabaseSchema crea una definició de BD segons els fitxers sq. - sqldelight/databases/1.db, 2.db, ... - A la carpeta sqldelight/migrations hi podem afegir fixers de migració. - El nom sempre es 1.sqm, 2.sqm ... - El 1.sqm és la migració per passar de la 1.db a 2.db - Les migracions s'executen soles (amb el DatabaseMigrationHelper) --- # Android - DriverFactory.android.kt ``` actual fun createDriver(): SqlDriver { val appContext = applicationContext return AndroidSqliteDriver(Database.Schema, appContext, "myDatabase.db") } ``` - Necessita el Context --- # Android - Context - Gradle ``` androidMain.dependencies { //... implementation("androidx.startup:startup-runtime:1.2.0") } ``` --- # Android - Context - ContextProvider.kt ``` internal lateinit var applicationContext: Context private set data object ContextProviderInitializer class ContextProvider: Initializer
{ override fun create(context: Context): ContextProviderInitializer { applicationContext = context.applicationContext return ContextProviderInitializer } override fun dependencies(): List
>> = emptyList() } ``` --- # Android - Context - AndroidManifest.xml ```xml
``` --- # Flow - Flow, stream, ... --- # Flow ``` suspend fun flowExample1() { val flow = flow { delay(2.seconds) emit("Hello") delay(2.seconds) emit("Bye") } println("Start listening flow") flow.collect { println(it) } } ``` --- # Flow - Flow, stream, ... ``` fun countDownFlow() = flow { repeat(10) { emit(it) delay(1.seconds) } } suspend fun flowExample2() { println("Start listening flow") countDownFlow().collect { println(it) } } ``` --- # Flow - Flow, stream, ... ``` /** * flow.map */ suspend fun flowExample3() { countDownFlow().map { it*2 }.collect { println(it) } } ``` --- # Flow sqldelight ``` val players: Flow
> = playerQueries.selectAll() .asFlow() .mapToList(Dispatchers.IO) ``` --- # Flow on Compose ``` @Composable fun myFun(flow: Flow
){ val value = flow().collectAsStateWithLifecycle("Loading...").value } ```