이전 강의에서 Words 앱을 만든적 있다. 이번 강의에서는 Preferences DataStore를 사용하여 기존 Words 앱을 개선한다. 기존 앱은 앱을 종료하고 다시 실행했을 때 사용자가 선택한 레이아웃 설정이 유지되지 않는다. Grid 레이아웃에서 앱을 종료해도 앱을 다시 실행하면 Linear 레이아웃으로 돌아가있다. 이 설정을 저장하여 앱을 다시 시작해도 설정이 유지되도록 할 것이다.
Preferences DataStore는 로그인 세부정보나 다크모드 설정, 글꼴 크기 등 작은 데이터셋을 저장하는데 적합하다. 대용량이나 복잡한 데이터셋을 저장해야 한다면 Room을 사용하는 것이 적합하다.
Preferences DataStore는 스키마를 정의하지 않고, 키-값 쌍으로 데이터에 액세스하거나 저장한다.
implementation "androidx.datastore:datastore-preferences:1.0.0"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"
private const val LAYOUT_PREFERENCES_NAME = "layout_preferences"
private val Context.dataStore : DataStore<Preferences> by preferencesDataStore(name = LAYOUT_PREFERENCES_NAME )
class SettingsDataStore(context: Context) {
private val IS_LINEAR_LAYOUT_MANAGER = booleanPreferencesKey("is_linear_layout_manager")
suspend fun saveLayoutToPreferencesStore(isLinearLayoutManager: Boolean, context: Context){
context.dataStore.edit { preferences ->
preferences[IS_LINEAR_LAYOUT_MANAGER] = isLinearLayoutManager
}
}
val preferenceFlow: Flow<Boolean> = context.dataStore.data
.catch {
if(it is IOException){
it.printStackTrace()
emit(emptyPreferences())
}else{
throw it
}
}
.map { preferense ->
preferense[IS_LINEAR_LAYOUT_MANAGER] ?: true
}
}
private const val LAYOUT_PREFERENCES_NAME = "layout_preferences"
layout_prefences는 인스턴스화할 Preferences DataStore의 이름이다.
private val Context.dataStore : DataStore<Preferences> by preferencesDataStore(name = LAYOUT_PREFERENCES_NAME )
DataStore 인스턴스를 생성한다.
saveLayoutToPreferencesStore()
는 Preferences DataStore에 쓰는 메서드이고, preferenceFlow는 Preferences DataStore에서 읽어온다.
catch()
연산자로 예외 처리도 추가한다.
LetterListFragment로 돌아가서 위에서 정의한 SettingsDataStore를 사용해보자.
먼저 상단에 lateinit으로 변수를 선언하고,
private lateinit var settingsDataStore: SettingsDataStore
onViewCreater()에서 변수를 초기화한다. 그리고 데이터 읽기와 관찰(observe)에 대한 코드를 추가한다.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
. . .
settingsDataStore = SettingsDataStore(requireContext())
settingsDataStore.prefenceFlow.asLiveData().observe(viewLifecycleOwner) { value ->
isLinearLayout = value
chooseLayout()
activity?.invalidateOptionsMenu()
}
}
onOptionsItemSelected()에도 아이콘이 눌렸을 때 preference datastore에 적용하도록 코드를 추가한다.
lifecycleScope.launch {
settingsDataStore.saveLayoutToPreferencesStore(isLinearLayout, requireContext())
}
이제 앱을 종료해도 다시 앱을 실행했을 때 사용자가 선택했던 레이아웃이 유지된다.