DataStore๋ ํค-๊ฐ ์ ํ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ก์ปฌ์ ์ ์ฅํ ์ ์๋ Jetpack์ ๋ฐ์ดํฐ ์ ์ฅ์ ์๋ฃจ์ ์ด๋ค. Coroutine ๋ฐ Flow๋ฅผ ์ฌ์ฉํด์ ๋น๋๊ธฐ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ฉฐ, SharedPreferences์ ๋ฌ๋ฆฌ UI ์ค๋ ๋ ํธ์ถ ๋ฐ ๋ฐํ์ ์๋ฌ๋ก๋ถํฐ ์์ ํ๋ค๋ ์ฅ์ ์ด ์๋ค. DataStore๋ ๋ณดํต ๊ฐ๋จํ ๋ฌธ์์ด๊ณผ ๊ฐ์ ์๊ท๋ชจ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ธฐ ์ํด ์ฌ์ฉํ๋ค(๋ณต์กํ๊ฑฐ๋ ๋๊ท๋ชจ์ ๋ฐ์ดํฐ๋ Room ์ฌ์ฉ์ ๊ถ์ฅํ๋ค). DataStore๋ 2๊ฐ์ง๋ก ๊ตฌ๋ถํ ์ ์๋ค.
Preferences DataStore๋ ํค๋ฅผ ์ฌ์ฉํด์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ ์ฝ์ด์จ๋ค. ์คํค๋ง๋ฅผ ์ ์ํ ํ์๋ ์์ง๋ง Proto DataStore์ ๋ฌ๋ฆฌ ์์ ์ฑ์ ์ ๊ณตํ์ง ์๋๋ค. Proto DataStore๋ ํ๋กํ ์ฝ ๋ฒํผ๋ฅผ ์ฌ์ฉํ์ฌ ์คํค๋ง๋ฅผ ์ ์ํด์ผ ํ๋ฉฐ, ์์ ์ฑ์ ์ ๊ณตํ๋ค. ๋ ์์ ํ๋ค๋ ๋ฉด์์ Proto DataStore๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๋ซ๊ฒ ์ง๋ง, ๋น ๋ฅด๊ฒ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ ์ถ์๋ ๋๋ ์ด์ ์ ์ฐ๋จนํด๋ดค๋ Preferences DataStore๋ฅผ ์ฌ์ฉํ๊ธฐ๋ก ํ๋ค.
DataStore๋ฅผ ์ฌ์ฉํ๊ธฐ ์ , build.gradle(module)์ preferences datastore์ ๋ํ ์ข ์์ฑ์ ์ถ๊ฐํ๋ค.
dependencies {
implementation("androidx.datastore:datastore-preferences:1.0.0")
}
๋จผ์ ๋๋ ์ฌ์ฉ์์ ์ด๋ฉ์ผ๊ณผ ์ด๋ค ๋ฐฉ์์ผ๋ก ๋ก๊ทธ์ธํ๋์ง(์ผ๋ฐ ๋ก๊ทธ์ธ์ธ์ง SNS ๊ณ์ ์ ์ด์ฉํ ๋ก๊ทธ์ธ์ธ์ง) ์ฌ๋ถ์ ๋ํด ์ ์ฅํ ๋ณ์๊ฐ ํ์ํ๋ค. ๋ฐ๋ผ์ DataStore๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ํด๋์ค๋ฅผ ์์ฑํ๊ณ , ๊ฐ ๊ฐ์ ์ ์ฅํ๊ณ ์ฝ๊ธฐ ์ํ key ๋ณ์์ ๋ํด ์ ์ธํ๋ค. key์ type์ ์ ์ฅํ๊ณ ์ ํ๋ ๋ณ์ ํ์ ์ ๋ฐ๋ผ ๋ค๋ฅด๊ฒ ์ ์ธํด์ค๋ค.
class DataStoreModule(private val context : Context){
//preferences DataStore ์์ฑ
//DataStore๋ฅผ ์ฑ๊ธํค์ผ๋ก ๊ด๋ฆฌํ๊ธฐ ์ํด ํ์ผ ์ต์๋จ์ ๋ฐฐ์น, ์ด๋ ๊ฒ ํ๋ฉด DataStore๋ฅผ ํ๋๋ง ์์ฑํ ์ ์์
private val Context.datastore by preferencesDataStore(name = "datastore")
private val emailKey = stringPreferencesKey("USER_EMAIL") //์ฌ์ฉ์์ ์ด๋ฉ์ผ
private val loginTypeKey = intPreferencesKey("LOGIN_TYPE") //๋ก๊ทธ์ธ ์ฌ๋ถ
}
๊ฐ์ ์ฝ์ด์ค๊ธฐ ์ํด DataStore.data๋ฅผ ์ฌ์ฉํ๋ค. map()์ ์ด์ฉํด DataStore์ ์ ์ฅ๋์ด ์๋ ๊ฐ์ ๋ฏธ๋ฆฌ ์ง์ ํด๋ ํค๋ฅผ ํตํด ๊ฐ์ ธ์จ๋ค. ์ด ๋ ๋ฐํ๋๋ ๊ฐ์ Flow์ด ๋๋ค.
๋ํ ๊ฐ์ ์ฝ์ด์ค๋๋ฐ์ ์คํจํ๋ฉด IOException์ด ๋ฐ์ํ ์ ์๋๋ฐ, catch()๋ฌธ์ ์ด์ฉํด exception์ด ๋ฐ์ํ์ ๊ฒฝ์ฐ ๋น ๊ฐ์ ์ ๋ฌํ๋๋ก ํ๋ค.
val email : Flow<String> = context.datastore.data
.catch{ exception ->
if(exception is IOException){
emit(emptyPreferences())
}else{
throw exception
}
}.map{
it[emailKey] ?: ""
}
DataStore์ ๊ฐ์ ์ ์ฅํ ๋๋ edit()์ ์ฌ์ฉํ๋ค. DataStore์ ๊ฐ์ ์ ์ฅํ ๋๋ ๋ฐ๋์ ๋น๋๊ธฐ๋ก ์์ ํด์ผ ํ๊ธฐ ๋๋ฌธ์, suspend๋ฅผ ํตํด ๊ฐ์ ์์ฑํ๋ ํจ์๊ฐ ์ฝ๋ฃจํด ์์ญ์์ ๋์ํ ์ ์๋๋ก ํ๋ค.
suspend fun setEmail(email : String){
context.datastore.edit{
it[emailKey] = email
}
}
DataStore๋ ์ฑ๊ธํค์ผ๋ก ๊ด๋ฆฌ๋์ด์ผ ํ๋ค. ๋ฐ๋ผ์ Application()์ ์์ํ๋ ํด๋์ค๋ฅผ ์์ฑํ๊ณ , DataStore ํด๋์ค์ context๋ก AppicationContext๋ฅผ ๋๊ฒจ์ค๋ค.
class App : Application() {
private lateinit var datastore : DataStoreModule
companion object{
private lateinit var app : App
fun getInstance() : App = app
}
override fun onCreate() {
super.onCreate()
app = this
datastore = DataStoreModule(this)
}
fun getDataStore() : DataStoreModule = datastore
}
์กํฐ๋นํฐ๋ ํ๋๊ทธ๋จผํธ์์ DataStore์ ๊ฐ์ ๊ฐ์ ธ์ฌ ๋๋ DataStore ํด๋์ค์์ ์ ์ธํ ๋ณ์์ ์ ๊ทผํ์ฌ Flow() ๊ฐ์ฒด๋ฅผ ๋ฐํ๋ฐ์ ๊ฐ์ ์ฝ์ด์์ผํ๊ธฐ ๋๋ฌธ์, ํด๋น ์์ ์ CoroutineScope ๋ด์์ ์คํํด์ผ ํ๋ค. ๋ง์ฝ ๋ด๊ฐ ์ํ๋ ํ์ด๋ฐ์ ํ ๋ฒ๋ง ๊ฐ์ ๋ฐ์์์ ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด first()๋ฅผ ํธ์ถํ๋ฉด ๋๋ค. ๊ฐ์ ์ ์ฅํ๋ ๊ฒ๋ ๋ง์ฐฌ๊ฐ์ง๋ก CoroutineScope ๋ด์์ ์คํํ๋ฉด ๋๋ค.
//๊ฐ ์ฝ์ด์ค๊ธฐ
CoroutineScope(Dispatchers.Main).launch{
val loginType = App.getInstance().getDataStore().email.first()
}
//๊ฐ ์ ์ฅํ๊ธฐ
CoroutineScope(Dispatchers.Main).launch {
App.getInstance().getDataStore().setEmail("user-email")
}
https://developer.android.com/topic/libraries/architecture/datastore?hl=ko
https://kangmin1012.tistory.com/47