Skip to content

Commit 6c5e044

Browse files
authored
Change CoroutineScope of preferences datastore, instead of redispatching (#325)
* Change CoroutineScope of preferences datastore, instead of redispatching * Change dispatcher of application scope to default, instead of IO dispatcher * Fix spotless
1 parent 124cc4e commit 6c5e044

File tree

3 files changed

+69
-35
lines changed

3 files changed

+69
-35
lines changed

core/kotlin/src/main/java/soup/movie/common/di/CoroutineScopesModule.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import kotlinx.coroutines.CoroutineDispatcher
2323
import kotlinx.coroutines.CoroutineScope
2424
import kotlinx.coroutines.SupervisorJob
2525
import soup.movie.common.ApplicationScope
26-
import soup.movie.common.MainImmediateDispatcher
26+
import soup.movie.common.DefaultDispatcher
2727
import javax.inject.Singleton
2828

2929
@Module
@@ -34,6 +34,6 @@ object CoroutineScopesModule {
3434
@Provides
3535
@ApplicationScope
3636
fun providesCoroutineScope(
37-
@MainImmediateDispatcher dispatcher: CoroutineDispatcher,
37+
@DefaultDispatcher dispatcher: CoroutineDispatcher,
3838
): CoroutineScope = CoroutineScope(SupervisorJob() + dispatcher)
3939
}

data/settings/impl/src/main/java/soup/movie/data/settings/impl/AppSettingsImpl.kt

Lines changed: 11 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,17 @@
1515
*/
1616
package soup.movie.data.settings.impl
1717

18-
import android.content.Context
1918
import androidx.datastore.core.DataStore
20-
import androidx.datastore.preferences.SharedPreferencesMigration
2119
import androidx.datastore.preferences.core.Preferences
2220
import androidx.datastore.preferences.core.edit
2321
import androidx.datastore.preferences.core.intPreferencesKey
2422
import androidx.datastore.preferences.core.stringPreferencesKey
25-
import androidx.datastore.preferences.preferencesDataStore
26-
import dagger.hilt.android.qualifiers.ApplicationContext
27-
import kotlinx.coroutines.CoroutineDispatcher
2823
import kotlinx.coroutines.CoroutineScope
2924
import kotlinx.coroutines.flow.Flow
3025
import kotlinx.coroutines.flow.first
3126
import kotlinx.coroutines.flow.map
3227
import kotlinx.coroutines.launch
33-
import kotlinx.coroutines.withContext
3428
import soup.movie.common.ApplicationScope
35-
import soup.movie.common.IoDispatcher
3629
import soup.movie.data.settings.AppSettings
3730
import soup.movie.model.settings.AgeFilter
3831
import soup.movie.model.settings.TheaterFilter
@@ -41,21 +34,10 @@ import javax.inject.Singleton
4134

4235
@Singleton
4336
class AppSettingsImpl @Inject constructor(
44-
@ApplicationContext private val context: Context,
45-
@IoDispatcher private val ioDispatcher: CoroutineDispatcher,
37+
private val preferences: DataStore<Preferences>,
4638
@ApplicationScope private val coroutineScope: CoroutineScope,
4739
) : AppSettings {
4840

49-
private val Context.preferencesName: String
50-
get() = packageName + "_preferences"
51-
52-
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(
53-
name = context.preferencesName,
54-
produceMigrations = { context ->
55-
listOf(SharedPreferencesMigration(context, context.preferencesName))
56-
},
57-
)
58-
5941
private val theaterFilterKey = intPreferencesKey("theater_filter")
6042

6143
init {
@@ -65,13 +47,13 @@ class AppSettingsImpl @Inject constructor(
6547
}
6648

6749
override suspend fun setTheaterFilter(theaterFilter: TheaterFilter) {
68-
context.dataStore.edit { settings ->
50+
preferences.edit { settings ->
6951
settings[theaterFilterKey] = theaterFilter.toFlags()
7052
}
7153
}
7254

7355
override fun getTheaterFilterFlow(): Flow<TheaterFilter> {
74-
return context.dataStore.data.map { preferences ->
56+
return preferences.data.map { preferences ->
7557
TheaterFilter(
7658
preferences[theaterFilterKey]
7759
?: TheaterFilter.FLAG_THEATER_ALL,
@@ -82,13 +64,13 @@ class AppSettingsImpl @Inject constructor(
8264
private val ageFilterKey = intPreferencesKey("age_filter")
8365

8466
override suspend fun setAgeFilter(ageFilter: AgeFilter) {
85-
context.dataStore.edit { settings ->
67+
preferences.edit { settings ->
8668
settings[ageFilterKey] = ageFilter.toFlags()
8769
}
8870
}
8971

9072
override fun getAgeFilterFlow(): Flow<AgeFilter> {
91-
return context.dataStore.data.map { preferences ->
73+
return preferences.data.map { preferences ->
9274
AgeFilter(
9375
preferences[ageFilterKey] ?: AgeFilter.FLAG_AGE_DEFAULT,
9476
)
@@ -98,10 +80,8 @@ class AppSettingsImpl @Inject constructor(
9880
private val themeOptionKey = stringPreferencesKey("theme_option")
9981

10082
override suspend fun setThemeOption(themeOption: String) {
101-
withContext(ioDispatcher) {
102-
context.dataStore.edit { settings ->
103-
settings[themeOptionKey] = themeOption
104-
}
83+
preferences.edit { settings ->
84+
settings[themeOptionKey] = themeOption
10585
}
10686
}
10787

@@ -110,17 +90,15 @@ class AppSettingsImpl @Inject constructor(
11090
}
11191

11292
override fun getThemeOptionFlow(): Flow<String> {
113-
return context.dataStore.data.map { preferences ->
93+
return preferences.data.map { preferences ->
11494
preferences[themeOptionKey].orEmpty()
11595
}
11696
}
11797

11898
private suspend fun clearStaleData() {
119-
withContext(ioDispatcher) {
120-
context.dataStore.edit { settings ->
121-
settings.remove(stringPreferencesKey("favorite_theaters"))
122-
settings.remove(stringPreferencesKey("favorite_genre"))
123-
}
99+
preferences.edit { settings ->
100+
settings.remove(stringPreferencesKey("favorite_theaters"))
101+
settings.remove(stringPreferencesKey("favorite_genre"))
124102
}
125103
}
126104
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2025 SOUP
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package soup.movie.data.settings.impl.di
17+
18+
import android.content.Context
19+
import androidx.datastore.core.DataStore
20+
import androidx.datastore.preferences.SharedPreferencesMigration
21+
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
22+
import androidx.datastore.preferences.core.Preferences
23+
import androidx.datastore.preferences.preferencesDataStoreFile
24+
import dagger.Module
25+
import dagger.Provides
26+
import dagger.hilt.InstallIn
27+
import dagger.hilt.android.qualifiers.ApplicationContext
28+
import dagger.hilt.components.SingletonComponent
29+
import kotlinx.coroutines.CoroutineDispatcher
30+
import kotlinx.coroutines.CoroutineScope
31+
import soup.movie.common.ApplicationScope
32+
import soup.movie.common.IoDispatcher
33+
import javax.inject.Singleton
34+
35+
@Module
36+
@InstallIn(SingletonComponent::class)
37+
object DataStoreModule {
38+
39+
@Provides
40+
@Singleton
41+
fun providesPreferencesDataStore(
42+
@ApplicationContext context: Context,
43+
@IoDispatcher ioDispatcher: CoroutineDispatcher,
44+
@ApplicationScope scope: CoroutineScope,
45+
): DataStore<Preferences> {
46+
val name = context.packageName + "_preferences"
47+
return PreferenceDataStoreFactory.create(
48+
scope = CoroutineScope(scope.coroutineContext + ioDispatcher),
49+
migrations = listOf(
50+
SharedPreferencesMigration(context = context, sharedPreferencesName = name),
51+
),
52+
) {
53+
context.preferencesDataStoreFile(name)
54+
}
55+
}
56+
}

0 commit comments

Comments
 (0)