DataStore๋ก ์ค์ ๊ฐ ์ ์ฅํ๊ธฐ
์ง๋ ๊ธ์์ ํ ์ผ ๋ชฉ๋ก ์ ์ฒด๋ฅผ Room์ ์ ์ฅํ๋ค. ์ด๋ฒ์ "๋คํฌ ๋ชจ๋ ์ผ์ง/๊บผ์ง"์ฒ๋ผ ๊ฐ ํ๋์ง๋ฆฌ ์ค์ ์ ์ ์ฅํด๋ณด์. ํ ์ผ ๋ชฉ๋ก์ฒ๋ผ ์ฌ๋ฌ ํ์ด ์๋ ํ
์ด๋ธ์ ๋ง๋๋ ๊ฑด ๊ณผํ๋ค.
์ Room ๋ง๊ณ DataStore์ธ๊ฐ
๊ฐ ํ๋ ์ ์ฅํ๋ ๋ฐ ํ
์ด๋ธ, Entity, Dao๋ฅผ ๋ค ๋ง๋๋ ๊ฑด ๋ฒ๊ฑฐ๋กญ๋ค. ์๋๋ก์ด๋์๋ ์๋ SharedPreferences๋ผ๋ ๋ ๊ฐ๋ฒผ์ด ์ ์ฅ์๊ฐ ์์๋๋ฐ, ์์ฆ์ ๊ทธ ์๋ฆฌ๋ฅผ DataStore๊ฐ ๋์ฒดํ๋ ์ถ์ธ๋ค. SharedPreferences๋ ์ ์ฅ/์กฐํ๊ฐ ๋๊ธฐ ํจ์๋ผ์ ๋ฉ์ธ ์ค๋ ๋๋ฅผ ๋ง์ ์ ์๋๋ฐ, DataStore๋ ์ฝ๋ฃจํด/Flow ๊ธฐ๋ฐ์ด๋ผ ๊ทธ๋ด ์ผ์ด ์๋ค.
์์กด์ฑ ์ถ๊ฐ
// app/build.gradle.kts
dependencies {
implementation("androidx.datastore:datastore-preferences:1.2.1")
}์ค์ ์ ์ฅ์ ๋ง๋ค๊ธฐ
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.preferencesDataStore
import android.content.Context
private val Context.settingsDataStore by preferencesDataStore(name = "settings")
private val DARK_MODE_KEY = booleanPreferencesKey("dark_mode")preferencesDataStore(name = "settings")๋ Context์ ๋ถ๋ ํ์ฅ ํ๋กํผํฐ(delegate)๋ฅผ ๋ง๋ค์ด์ค๋ค. ์ด๊ฑธ ํธ์ถํ๋ ์ชฝ์์๋ context.settingsDataStore๋ก ๋ฐ๋ก ๊บผ๋ด ์ธ ์ ์๊ณ , ๋ด๋ถ์ ์ผ๋ก๋ "settings"๋ผ๋ ์ด๋ฆ์ ํ์ผ ํ๋๋ก ๊ด๋ฆฌ๋๋ค. booleanPreferencesKey("dark_mode")๋ ๊ทธ ์์์ Boolean ๊ฐ ํ๋๋ฅผ ์ฐพ์ ๋ ์ฐ๋ ์ด์ ๋ค. ๋ฌธ์์ด ์ด์ ์ง๋ง, ํ์
์ด Boolean์ด๋ผ๊ณ ๋ฏธ๋ฆฌ ์ ํด๋๊ธฐ ๋๋ฌธ์ ๋์ค์ ๊บผ๋ผ ๋ ํ์
์ ๋ค์ ์ง์ ํ ํ์๊ฐ ์๋ค.
์ฝ๊ธฐ์ ์ฐ๊ธฐ
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.core.DataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
class SettingsRepository(private val dataStore: DataStore<Preferences>) {
val isDarkMode: Flow<Boolean> = dataStore.data.map { preferences ->
preferences[DARK_MODE_KEY] ?: false
}
suspend fun setDarkMode(enabled: Boolean) {
dataStore.edit { preferences ->
preferences[DARK_MODE_KEY] = enabled
}
}
}dataStore.data๋ ์ ์ฅ๋ ์ค์ ์ ์ฒด๋ฅผ Flow<Preferences>๋ก ํ๋ ค๋ณด๋ธ๋ค. DARK_MODE_KEY๋ก ๊ทธ์ค ๋คํฌ ๋ชจ๋ ๊ฐ๋ง ๊บผ๋ด๊ณ , ๊ฐ์ด ํ ๋ฒ๋ ์ ์ฅ๋ ์ ์์ผ๋ฉด(null) ๊ธฐ๋ณธ๊ฐ false๋ฅผ ์ด๋ค. edit { ... } ๋ธ๋ก ์์์ ๊ฐ์ ๋ฐ๊พธ๋ฉด, ๊ทธ ๋ณ๊ฒฝ์ด ๋์คํฌ์ ๋ฐ์๋๊ณ isDarkMode๋ฅผ ๊ตฌ๋
ํ๋ ์ชฝ์๋ ์ ๊ฐ์ด ํ๋ฌ๊ฐ๋ค. Room์ Dao๊ฐ Flow๋ก ํ
์ด๋ธ ๋ณํ๋ฅผ ํ๋ ค๋ณด๋ธ ๊ฒ๊ณผ ๋๊ฐ์ ์๋ฆฌ๋ค.
ViewModel์ ์ฐ๊ฒฐ
class TodoViewModel(application: Application) : AndroidViewModel(application) {
private val settingsRepository = SettingsRepository(application.settingsDataStore)
val isDarkMode: StateFlow<Boolean> = settingsRepository.isDarkMode
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), false)
fun toggleDarkMode(enabled: Boolean) {
viewModelScope.launch { settingsRepository.setDarkMode(enabled) }
}
// ... ์ง๋ ๊ธ์ todoList ๊ด๋ จ ์ฝ๋๋ ๊ทธ๋๋ก
}[์ด๋ฏธ์ง: ๋คํฌ ๋ชจ๋ ์ค์์น๋ฅผ ์ผ ํ๋ฉด, ๊ทธ๋ฆฌ๊ณ ์ฑ์ ์ฌ์์ํด๋ ๋คํฌ ๋ชจ๋๊ฐ ์ ์ง๋ ํ๋ฉด]
์ง๊ธ๊น์ง ๋ดค๋ ํ๋ฆ๊ณผ ๋๊ฐ๋ค. ์ ์ฅ์(SettingsRepository)๊ฐ Flow๋ฅผ ๋ด๋๊ณ , ViewModel์ด ๊ทธ๊ฑธ stateIn()์ผ๋ก StateFlow๋ก ๋ฐ๊พธ๊ณ , ์ปดํฌ์ ๋ธ์ collectAsStateWithLifecycle()๋ก ๊ตฌ๋
ํ๋ค. ์ ์ฅ ์๋จ์ด Room์ด๋ DataStore๋๋ง ๋ค๋ฅผ ๋ฟ, ViewModel ์์ชฝ(์ปดํฌ์ ๋ธ)์์ ๋ณด์ด๋ ๋ชจ์์ ๊ฑฐ์ ๋๊ฐ๋ค.
์ ๋ฆฌ
- ์ฌ๋ฌ ํ์ด ์๋ ๋ฐ์ดํฐ๋
Room, ์ค์ ๊ฐ ํ๋์ง๋ฆฌ๋DataStore๋ฅผ ์ด๋ค DataStore๋Room์ฒ๋ผFlow๋ก ๊ฐ์ ํ๋ ค๋ณด๋ด๊ณ ,edit { }์ผ๋ก ๊ฐ์ ๋ฐ๊พผ๋ค- ์ ์ฅ ์๋จ์ด ๋ฐ๋์ด๋
ViewModel์์ชฝ ๊ตฌ์กฐ(StateFlowโcollectAsStateWithLifecycle)๋ ๋๊ฐ์ด ์ ์ง๋๋ค
๋ค์ ๊ธ์์๋ ์๋ฒ์์ ํ ์ผ ๋ชฉ๋ก์ ๊ฐ์ ธ์ค๋ ๊ฑธ Retrofit์ผ๋ก ํด๋ณด๊ณ , ๋ก๋ฉ ์ค/์๋ฌ ์ํ๋ฅผ UiState์ ์ด๋ป๊ฒ ๋ด๋์ง ๋ณด๊ฒ ๋ค.
