I am trying to persist some simple state of my android app using preferences with Jetpack DataStore. I want to fill the value of a key with a default value if there was nothing stored yet. However when I try to find out if there is a value for the key present the library call completely stops the execution of my whole function.
package com.example.spielwiese
import android.content.Context
import android.os.Bundle
import android.util.Log
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.stringSetPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.count
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
val Context.dataStore: DataStore<Preferences> by preferencesDataStore("settings")
class MainActivity : AppCompatActivity() {
private val scopeIo = CoroutineScope(Job() + Dispatchers.IO)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
scopeIo.launch { checkPreferences() }
}
private suspend fun checkPreferences() = withContext(Dispatchers.IO) {
Log.d("HUGELBUGEL", "Before dataStore access.")
val nothingThere = dataStore.data.map { preferences ->
preferences[stringSetPreferencesKey("myKey")]
}.count() == 0
// This log doesn't come out
Log.d("HUGELBUGEL", "After dataStore access: $nothingThere")
// if (nothingThere) putDefaultValueIntoDataStore()
}
}
The first log comes out at runtime, but the second doesn't. I tried to debug it, but when it comes to the call of count() it just never comes back. I don't even know what's happending here. There is no exception (I tried to catch one), no nothing, it just stops execution there. Maybe I don't understand kotlin coroutines well enough, but even then: Why does it just stop execution and doesn't throw an exception there? Did I use the DataStore wrong? What can I do to fix it?
My build.gradly.kts for the app module looks like this:
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
}
android {
namespace = "com.example.spielwiese"
compileSdk = 34
defaultConfig {
applicationId = "com.example.spielwiese"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
implementation(libs.androidx.datastore.preferences)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
}
It's all default stuff, that AndroidStudio creates for you, when creating a new Project, just added the nessecary code for the question here.