728x90
언제 쓸까?
로그인 세부 정보 저장, 다크모드 설정, 글꼴 크기 등 작고 간단한 데이터 세트에 적합
대용량 or 복잡한 데이터 → Room을 쓰자.
Jetpack DataStore 라이브러리 → 데이터 저장을 위한 간단하고 안전한 비동기
- Preference DataStore : key-value로 저장
- Proto DataStore : 프로토콜 버퍼를 사용하여 스키마 정의 → Strong Type 데이터 유지 가능
Proto DataStore는 type safety, 효율적이지만 구성과 설정이 필요함
Preference DataStore는 쉽게 설정 가능
필수 추가 종속성
implementation("androidx.datastore:datastore-preferences:1.0.0")
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.3.1")
Preference Datastore 설정 방법
@ActivityRetainedScoped
class LocalUserDataStore @Inject constructor(
private val localDataStore: DataStore<Preferences>,
) {
private object Keys {
val id = stringPreferencesKey(ID_KEY)
val password = stringPreferencesKey(PASSWORD_KEY)
val nickname = stringPreferencesKey(NICKNAME_KEY)
}
val userInfo: Flow<UserInfo> = localDataStore.data
.catch {
if (it is IOException) {
emit(emptyPreferences())
} else {
throw it
}
}
.map { preferences ->
UserInfo(
id = preferences[Keys.id].orEmpty(),
password = preferences[Keys.password].orEmpty(),
nickname = preferences[Keys.nickname].orEmpty(),
)
}
.distinctUntilChanged()
suspend fun setUserInfo(userInfo: UserInfo) {
localDataStore.edit { preferences ->
preferences[Keys.id] = userInfo.id
preferences[Keys.password] = userInfo.password
preferences[Keys.nickname] = userInfo.nickname
}
}
companion object {
const val ID_KEY = "id_key"
const val PASSWORD_KEY = "pw_key"
const val NICKNAME_KEY = "nickname_key"
}
}
DataStore 객체 밖에서 선언하여 싱글톤으로 관리
나는 SSA설계를 위해 ActivityRetainedScoped를 사용했지만, 싱글톤을 적용해주는게 일반적인 상황에선 더 좋을 것 같다
@ActivityRetainedScoped를 사용하여 액티비티의 생명주기를 따라가도록 설정
- @ActivityRetainedScoped : Activity의 onCreate()와 onDestory()를 그대로 따라감
- @ActivityScoped : Configuration Change에 영향을 받지 않음 ex) 화면 회전…
Preference Datastore에 값을 저장하는 방법
suspend fun setUserInfo(userInfo: UserInfo) {
context.localDataStore.edit { preferences ->
preferences[Keys.id] = userInfo.id
preferences[Keys.password] = userInfo.password
preferences[Keys.nickname] = userInfo.nickname
}
}
Preference Datastore에서 값을 가져오는 방법
val userInfo: Flow<UserInfo> = context.localDataStore.data
.catch {
if (it is IOException) {
emit(emptyPreferences())
} else {
throw it
}
}
.map { preferences ->
UserInfo(
id = preferences[Keys.id].orEmpty(),
password = preferences[Keys.password].orEmpty(),
nickname = preferences[Keys.nickname].orEmpty(),
)
}
.distinctUntilChanged()
728x90