위치 기록 앱을 만들면서 저번엔 Compose GoogleMap에 대한 글을 작성했고
이번엔 위도와 경도를 어떻게 기록했는지에 대해 공유하고자 한다.
처음엔 익숙한 Room 라이브러리를 사용해서 기록하려 했지만 생각해보니 너무 비효율 적이라고 생각했다.
고작 위도와 경도 값만 저장하면 되는 상황이기 때문이였다.
대신 SharedPreferences를 사용하여 훨씬 간단하게 값을 저장하려고 했는데
현재 안드로이드에서 DataStore의 사용을 권장하고 있다는 게 생각이났다.
안드로이드 앱에서 데이터를 저장하고 관리하기 위한 Jetpack 라이브러리이다.
SharedPreferece에 비해 다음과 같은 장점을 가지고 있다.
DataStore를 검색해보면 무조건 볼 수 있는 표인데
DataStore를 안 쓸 이유가 없을 것 같다.
먼저 DataStore를 생성해준다.
class DataStoreModule(private val context: Context) {
/**
* DataStore는 무조건 싱글톤으로 관리되어야 한다.
* 당연한 얘기지만 DataStore 객체가 중복으로 생성됐을 경우 저장한 값의 안정성이 위반된다.
*/
companion object {
// DataSotre 생성
private val Context.dataStore by preferencesDataStore(name = "dataStore")
// 위도 경도 저장 키값 타입에 맞게 double로 선언하였다.
private val latitudeKey = doublePreferencesKey("latitude")
private val longitudeeKey = doublePreferencesKey("longitude")
}
/**
* DataStore에서 값 읽기
* Flow로 값을 받아온다.
* 예외가 발생했을 경우를 대비해 catch를 사용하여 예외처리를 한다.
* map을 이용해서 저장되어있는 값을 키를 통해 가져온다.
*/
val getLatitude: Flow<Double> = context.dataStore.data
.catch { exception ->
if (exception is IOException) {
emit(emptyPreferences())
} else {
throw exception
}
}
.map { preference ->
preference[latitudeKey] ?: 0.0
}
val getLongitude: Flow<Double> = context.dataStore.data
.catch { exception ->
if (exception is IOException) {
emit(emptyPreferences())
} else {
throw exception
}
}
.map { preference ->
preference[longitudeeKey] ?: 0.0
}
/**
* DataStore 값 쓰기
* 쓰기는 비동기로 처리되기 때문에 suspend를 붙여준다.
*/
suspend fun saveLatitude(latitude: Double) {
context.dataStore.edit { preference ->
preference[latitudeKey] = latitude
}
}
suspend fun saveLongitude(longitude: Double) {
context.dataStore.edit { preference ->
preference[longitudeeKey] = longitude
}
}
}
val dataStore = DataStoreModule(context)
val latLng = getMyLocation(context)
scope.launch {
dataStore.saveLatitude(latLng.latitude)
dataStore.saveLongitude(latLng.longitude)
Toast.makeText(context, "기록 되었습니다.", Toast.LENGTH_SHORT).show()
}
DataStoreModule 인스턴스를 생성한다
DataStoreModule의 위에서 작성한 함수를 호출하여 값을 넣어준다
비동기로 동작하기 때문에 코루틴 블록 내부에서 실행한다
val dataStore = DataStoreModule(context)
var savedLatitude by remember {
mutableDoubleStateOf(0.0)
}
var savedLongitude by remember {
mutableDoubleStateOf(0.0)
}
LaunchedEffect(Unit) {
dataStore.getLatitude.collect {
savedLatitude = it
}
}
LaunchedEffect(Unit) {
dataStore.getLongitude.collect {
savedLongitude = it
}
}