안드로이드

[Android/Kotlin] (작은) 키-값 데이터 저장 : SharedPreference API (=공유 환경 설정)

란서 2022. 5. 31. 12:38

SharedPreference API


저장하려는 키-값 컬렉션이 비교적 작은 경우 SharedPreference API를 사용.

SharedPreference 객체는 키-값 쌍이 포함된 파일을 가리키며 키-값 쌍을 읽고 쓸 수 있는 간단한 메서드를 제공한다.

키-값 쌍이 저장된 각 SharedPreference 파일은 프레임워크에서 관리하며 비공개이거나 공유일 수 도 있다. 

*비공개 또는 공유 여부는 "Context.MODE_ ~ " 인자를 이용한다.

※주의 : SharedPreference API 와 Preference API를 혼동하지 말것.

SharedPreference API 키-값 쌍을 읽고 쓰는 데 사용된다.

반면에 Preference API 앱 설정을 위한 사용자 인터페이스 빌드를 지원한다.

 

 

SharedPreference 의 Handle 가져오기


두 가지 메서드 중 하나를 이용하여 새로운 SharedPreference 파일을 생성하거나 기존 파일에 접근할 수 있다.


  • getSharedPreferences() 

    이름으로 식별되는 SharedPreference 파일이 여러 개 필요한 경우 해당 메서드를 사용.
    이름첫 번째 매개변수로 지정할 수 있다. 앱의 모든 Context에서 이 메서드를 호출 가능.

  • getPreferences()

    활동에 공유 환경설정 파일을 하나만 사용해야 하는 경우 Activity에서 이 메서드를 사용.
    이 메서드는 활동에 속한 기본 공유 환경설정 파일을 검색하기 때문에 따로 이름을 제공할 필요 없음.

1. getSharedPreference() 예시.

val sharedPref = activity?.getSharedPreferences(
        getString(R.string.preference_file_key), Context.MODE_PRIVATE)

-> activity 또는 fragmentcontext에서 호출 가능.

-> 첫번째 매개변수로 이름을 넣어주기 위해 getString(R.string.preference_file_key) 문자열을 가져옴.
-> 해당 SharedPreference 파일을 비공개 모드로 지정해주기 위해 Context.MODE_PRIVATE 를 인자로 넣어줌. 

 

참고 : 이름을 지정할 때 앱에 고유하게 식별할 수 있는 문자열을 사용해야 한다.
파일 이름 앞에 애플리케이션 ID를 붙이는 것을 권장. 

ex) "com.example.myapp.PREFERENCE_FILE_KEY"

 

2. getPreferences() 예시.

val sharedPref = activity?.getPreferences(Context.MODE_PRIVATE)

->activity에서 호출 가능. 
->이름 지정할 필요 없음
->비공개 모드로 지정.


참고 : 앱 설정을 저장하는데 (= Preference API) 만약 SharedPreferences API를 사용하고 있다면 
대신 getDefaultSharedPreferences()를 사용하여 전체 앱의 기본 SharedPreferences 파일을 가져와야 한다.

 

 

SharedPreference 쓰기


SharedPreference 파일에 쓰려면 SharedPreferences에서 edit()를 호출하여 SharedPreferences.Editor를 만든다.

참고 : 만약 더 안전하게 데이터를 사용하려면 SharedPreferences가 아닌 EncryptedSharedPreferences 객체에서 edit() 메서드를 호출하여 안전하게 파일을 수정할 수 있다.

 

 

SharedPreferences.Editor 를 사용하여 putInt()putString() 과 같은 메서드를 사용하여 쓰려는 키-값 쌍을 전달한다.
그런 다음 apply() 또는 commit()를 호출하여 변경사항을 저장한다. 

val newHighScore = 255
val sharedPref = activity?.getPreferences(Context.MODE_PRIVATE) ?: return
with (sharedPref.edit()) {
    putInt(getString(R.string.saved_high_score_key), newHighScore)
    apply()
}

-> putInt()를 이용해 키-쌍 값을 전달.
-> apply()를 호출해 변경사항 저장

 

참고 : 
apply()메모리 내 SharedPreferences 객체를 즉시 변경하지만 업데이트를 디스크에 비동기적으로 쓴다.

commit() 데이터를 디스크에 동기적으로 쓸 수 있다.
하지만 동기적이므로 UI렌더링이 일시 중단될 수 있기 때문에 main 스레드에서 호출하는 것을 피해야 한다.

 

 

SharedPreferenced 읽기


SharedPreference 파일에서 값을 검색하려면 getInt() 및 getString() 과 같은 메서드를 호출한다.

원하는 값에 키를 제공하고 만약 키가 없으면 선택적으로 반환할 기본값을 제공한다.

val sharedPref = activity?.getPreferences(Context.MODE_PRIVATE) ?: return
val defaultValue = resources.getInteger(R.integer.saved_high_score_default_key)
val highScore = sharedPref.getInt(getString(R.string.saved_high_score_key), defaultValue)

-> activity.getPreferences() 로부터 SharedPreference 의 Handle가져오기.
-> 키가 없을 경우에 받아올 기본값 defaultValue 설정
-> Handle로부터 getInt() 호출하고 원하는 값에 키를 제공하여 값 받아오기.



실제 사용 


private lateinit var sharedPrefStr: SharedPreferences
private lateinit var sharedPrefBool: SharedPreferences

...

        sharedPrefBool = this.context?.getSharedPreferences(
            getString(R.string.com_example_solaroid_LoginSaveKeyBool),
            Context.MODE_PRIVATE
        ) ?: return

        sharedPrefStr = this.context?.getSharedPreferences(
            getString(R.string.com_example_solaroid_LoginSaveKeyStr),
            Context.MODE_PRIVATE
        ) ?: return

 

fragment.context.getSharedPreferences() 메서드를 이용하여 SharedPreference 의 handle 가져오기.

boolean 타입과 string 타입 두 개의 값을 쓰고 읽기 위해 sharedPreferences의 handle 또한 2개를 설정. 
-> 따라서 파일이 여러개 필요하니까 그만큼  각자 다른 이름 을 지정해주었다.