일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 부스트코스
- 안드로이드 sunflower
- 막내의막무가내 코틀린 안드로이드
- flutter network call
- 막내의 막무가내 알고리즘
- 막내의막무가내 프로그래밍
- 막내의막무가내 알고리즘
- Fragment
- 안드로이드
- 막내의막무가내 코볼 COBOL
- 막내의막무가내 플러터 flutter
- 막내의막무가내
- 막내의막무가내 코틀린
- 주엽역 생활맥주
- 막내의막무가내 일상
- 막내의막무가내 플러터
- 막내의막무가내 목표 및 회고
- 막내의막무가내 안드로이드 에러 해결
- 막내의막무가내 rxjava
- 주택가 잠실새내
- 막내의막무가내 안드로이드
- 막내의막무가내 안드로이드 코틀린
- 막내의 막무가내
- 2022년 6월 일상
- 프로그래머스 알고리즘
- 막내의막무가내 SQL
- 막무가내
- 부스트코스에이스
- 프래그먼트
- 안드로이드 Sunflower 스터디
- Today
- Total
막내의 막무가내 프로그래밍 & 일상
[안드로이드] 새로운 저장소 Jetpack DataStore (feat. Sharedpreferences 를 대체) 본문
[안드로이드] 새로운 저장소 Jetpack DataStore (feat. Sharedpreferences 를 대체)
막무가내막내 2020. 9. 3. 12:37
[2021-04-14 업데이트]
안드로이드 Jetpack 에서 DataStore 가 나왔습니다. 이에 대해 문서를 보며 확실히 공부도 하고 영어도 해석할 겸 포스팅합니다. (아직 한국어 나오기전입니다)
Jetpack DataStore는 데이터 스토리지 솔루션이며 key-value pairs 나 objects 타입을 protocol buffers로 저장이 가능합니다. DataStore는 코틀린 코루틴과 Flow 를 사용하여 asynchronously, consistently, transactionally 하게 데이터를 저장합니다.
만약 현재 Sharedpreferences 를 사용중이라면 DataStore로 migrating를 고려합시다.
Note: If you need to support large or complex datasets, partial updates,
or referential integrity, consider using Room instead of DataStore.
DataStore is ideal for small, simple datasets and
does not support partial updates or referential integrity.
복잡하고 큰 용량의 데이터를 사용하면 Room 을 사용합시다.
Preferences DataStore and Proto DataStore
DataStore는 두 가지 다른 구현을 갖고있습니다. Preferences DataStore and Proto DataStore 입니다.
1. Preferences DataStore 는 key를 사용하여 데이터에 저장 및 접근을 합니다. 이 구현체는 스키마를 미리 정의할 것을 요구하지 않고 type safety 또한 제공하지 않습니다.
2. Photo DataStore 는 커스텀 데이터 타입의 인스턴스 데이터를 저장하는데 사용합니다. 이 구현체는 protocol buffers를 사용하여 schema 를 정의하는게 필요하고 type safety 를 제공합니다.
Setup
build.gradle 에 다음을 추가하여 사용할 수 있습니다.
dependencies {
// Preferences DataStore
implementation "androidx.datastore:datastore-preferences:1.0.0-alpha01"
// Proto DataStore
implementation "androidx.datastore:datastore-core:1.0.0-alpha01"
}
Store key-value pairs with Preferences DataStore
Preferences DataStore 는 DataStore 와 Preferences class 들을 사용하여 심플한 key-value 쌍으로 디스크에 보존합니다.
Create a Preferences DataStore
Context.createDataStore() 확장 함수를 사용해 DataStore<Preferences> 인스턴스를 생성합니다. Preferences DataStore의 name은 필수 파라미터 입니다.
val dataStore: DataStore<Preferences> = context.createDataStore(
name = "settings"
)
Read from a Preferences DataStore
Preferences DataStore 는 schema를 미리 정의하지 않기 때문에, Preferences.preferencesKey() 를 사용하여 DataStore<Preferences> 인스턴스에 저장이 필요한 key 와 각각의 value를 정의해줘야 합니다. 그 다음, Flow를 사용하여 적절한 value 를 expose 해주기 위해 DataStore.data 프로퍼티를 사용합니다.
val EXAMPLE_COUNTER = preferencesKey<Int>("example_counter")
val exampleCounterFlow: Flow<Int> = dataStore.data
.map { preferences ->
// No type safety.
preferences[EXAMPLE_COUNTER] ?: 0
}
Write to a Preferences DataStore
Preferences DataStore 는 edit() 함수를 제공하고 transactionally 하게 DataStore에 데이터를 업데이트 시켜줍니다. 함수의 transform parameter 는 사용자가 값 업데이트가 필요할 때마다 코드의 block을 허용합니다. transform block 안에 있는 모든 코드는 single transaction으로 다루어집니다.
suspend fun incrementCounter() {
dataStore.edit { settings ->
val currentCounterValue = settings[EXAMPLE_COUNTER] ?: 0
settings[EXAMPLE_COUNTER] = currentCounterValue + 1
}
}
Store typed objects with Proto DataStore
Proto DataStore 구현체는 object 타입을 디스크에 저장하기 위해 DataStore와 protocol buffers 를 사용합니다.
Define a schema
Proto DataStore 는 app/src/main/proto/ 디렉토리 안의 proto file 의 스키마를 미리 정의해야합니다. 이 스키마는 Proto DataStore 에 저장할 object 타입을 정의합니다. proto schema 정의에 대해 더 공부하고 싶다면 다음을 참고하면 됩니다. protobuf language guide.
syntax = "proto3";
option java_package = "com.example.application";
option java_multiple_files = true;
message Settings {
int example_counter = 1;
}
Note: The class for your stored objects is generated at compile time
from the message defined in the proto file. Make sure you rebuild your project.
Create a Proto DataStore
Proto DataStore 를 생성하고 Typed Objects 를 저장하는데 두 가지 단계가 있습니다.
1. 클래스가 Serializer<T> 를 implements 해야합니다. 이 때 T 는 proto file 안의 타입을 정의해주면 됩니다. serializer class 는 DataStore 가 사용자의 데이터 타입을 어떻게 읽고 쓸지 알려줍니다.
2. Context.createDataStore() 확장 함수를 사용하여 DataStore<T> 인스턴스를 생성합니다. 이 때 T 는 proto file 안의 타입입니다. fileName 파라미터는 DataStore 에게 저장할 데이터를 위해 사용할 file 을 알려주고 serializer 파라미터는 1번 단계에서 정의한 serializer 클래스의 이름을 DataStore에게 알려줍니다.
object SettingsSerializer : Serializer<Settings> {
override fun readFrom(input: InputStream): Settings {
try {
return Settings.parseFrom(input)
} catch (exception: InvalidProtocolBufferException) {
throw CorruptionException("Cannot read proto.", exception)
}
}
override fun writeTo(
t: Settings,
output: OutputStream) = t.writeTo(output)
}
val settingsDataStore: DataStore<Settings> = context.createDataStore(
fileName = "settings.pb",
serializer = SettingsSerializer
)
Read from a Proto DataStore
저장된 object로부터 적절한 프로퍼티의 플로우를 제공하기 위해 DataStore.data 를 사용합니다.
val exampleCounterFlow: Flow<Int> = settingsDataStore.data
.map { settings ->
// The exampleCounter property is generated from the proto schema.
settings.exampleCounter
}
Write to a Proto DataStore
Proto DataStore는 저장된 object를 transactionally 하게 업데이트 해주는 updateData() 함수를 제공합니다. updataData() 는 데이터 타입의 인스턴스로 데이터의 현재 상태를 주고 data 를 atomic read-write-modify operation 를 통해 transactionally 하게 데이터를 업데이트 해줍니다.
suspend fun incrementCounter() {
settingsDataStore.updateData { currentSettings ->
currentSettings.toBuilder()
.setExampleCounter(currentSettings.exampleCounter + 1)
.build()
}
}
SharedPrefernces 와 비교하여 좋은 옵션들이 추가되었습니다. 아직 코루틴을 예전에 한번보고 자세히 공부하지않아 Flow는 잘 모르는데 코루틴을 밀어주는게 확실히 보이는 것 같습니다.
댓글과 공감은 큰 힘이 됩니다. 감사합니다. !!
[참고 및 출처]
android-developers.googleblog.com/2020/09/prefer-storing-data-with-jetpack.html
developer.android.com/topic/libraries/architecture/datastore
codelabs.developers.google.com/codelabs/android-preferences-datastore/#0
codelabs.developers.google.com/codelabs/android-proto-datastore/#0