[Android] 7(2). SharedPreferences

4 minute read


SharedPreferences

안드로이드는 간단한 데이터(로그인 정보나 앱의 상태 정보 등)를 저장할 목적으로 SharedPreferences를 제공합니다. SharedPreferences는 내부 저장소를 이용하기 때문에 권한 설정이 필요없고 훨씬 간단한 코드로 사용할 수 있습니다.

image-20210812115829496

SharedPreferences는 액티비티에서 인텐트에 값을 넣고 빼는 것과 비슷하게 동작합니다.


SharedPreferences를 사용하고 데이터 저장하기


SharedPreferences는 인텐트에 값을 전달하듯이 데이터를 키와 값 쌍으로 저장합니다. 데이터는 XML 형식으로 된 파일로 저장되며 앱이 종료되어도 남아있습니다.


SharedPreferences 사용하기

  • 값 저장하기
    1. SharedPreferences 생성하기
    2. Editor 꺼내기
    3. putInt( ), putString( ) 메서드로 저장하기
    4. apply( )로 파일에 반영하기
  • 값 읽어오기
    1. SharedPreferences 생성하기
    2. getInt( ), getString( ) 메서드로 값 읽어오기


getSharedPreferences( )

getSharedPreferences( )는 Context를 가지고 있는 모든 컴포넌트에서 접근과 호출이 가능합니다. 파라미터로 ‘데이터가 저장될 파일명과 파일 접근 권한’를 전달하면 SharedPreferences가 생성되어 반환됩니다.

val shared = getSharedPreferences("파일명", Context.MODE_PRIVATE)

모드에는 MODE_PRIVATE, MODE_WORLD_READABLE, MODE_WORLD_WRITEABLE이 있지만, API Level 17부터 보안상의 이유로 MODE_PRIVATE만 사용합니다.


getPreferences( )

개별 액티비티에섯 사용하거나 액티비티가 하나밖에 없는 앱이라면 getPreferences( )를 호출합니다. 호출하는 액티비티의 이름으로 저장 파일이 생성됩니다.

var preferences = getPreferences(Context.MODE_PRIVATE)


Editor로 데이터를 저장하고 불러오기

SharedPreferences로 데이터를 저장하기 위해서는 Editor 인터페이스를 사용해야 하며, edit( ) 메서드를 호출해서 사용할 수 있습니다.

val shared = getSharedPreferences("파일명", Context.MODE_PRIVATE)
val editor = shared.edit()

데이터를 저장할 때는 입력될 값의 타입에 맞는 Editor 메서드를 사용합니다.

마지막에 apply( ) 메서드를 호출해야만 실제 파일에 반영됩니다.

val shared = getSharedPreferences("파일명", Context.MODE_PRIVATE)
val editor = shared.edit()
editor.putString("키", "값")
editor.apply()

데이터 저장 메서드로는 putFloat, putLong, putInt, putBoolean, putString, putStringSet 이 있으며 key값으로는 String 타입만 가능합니다.


반면, 데이터를 불러올 때는 데이터를 저장할 때와는 다르게 Editor를 사용하지 않고 SharedPreferences의 메서드를 직접 호출해서 읽어옵니다.

두번째 파라미터인 defaultValue를 지정하면 해당 키의 데이터가 없을 시 지정한 기본값을 반환합니다.

val shared = getSharedPreferences("파일명", Context.MODE_PRIVATE)
shared.getString("키", "기본값")

데이터를 읽어오는 메서드도 마찬가지로 getFloat, getLong, getInt, getBoolean, getString, getStringSet 이 있으며 두번째 파라미터로 ‘기본값’을 지정할 수 있습니다.


데이터 쓰기/읽기 외에도 Editor를 사용해서 삭제도 할 수 있습니다. 삭제 처리 후에도 반드시 apply( ) 메서드를 호출해야합니다.

메서드 설명
remove(String key) 해당 키의 데이터를 삭제합니다.
clear( ) 모든 데이터를 삭제합니다.
apply( ) 변경한 업데이트를 파일에 비동기적으로 저장합니다.
commit( ) 변경한 업데이트를 파일에 동기적으로 저장합니다. 동기 작업이므로 UI 스레드에서
호출하는 것을 피해야 합니다.

commit( )은 메인 스레드(UI 스레드)를 사용하기 때문에 짧은 순간이지만 화면이 멈출 수 있습니다. 따라서 특별한 경우가 아니면 항상 apply 메서드를 사용하는 것이 좋습니다.



설정 화면 만들기


안드로이드 10부터는 레이아웃 파일을 이용해서 화면을 구성하지 않도록 AndroidX Preferences 라이브러리의 PreferencesFragment를 사용해 설정 화면을 만들 수 있습니다.

AndroidX Preferences 의존성 추가하기 

1. androidX.preferences 의존성 추가

모듈의 gradle 파일의 dependencies에 다음을 입력합니다.

// SharedPreferences 라이브러리 의존성 추가
def preference_version = "1.1.1"
implementation "androidx.preference:preference-ktx:$preference_version"


PreferenceScreen 화면 정의하기

2. preferences.xml 파일 생성

preferences.xml 파일에 설정 화면에서 사용할 화면 구조를 XML로 정의해두면 안드로이드가 정의된 XML의 구조를 분석해서 화면을 그려줍니다.

[res] 마우스 우클릭 - [New] - [Android Resource File] 을 선택하여 다음과 같이 입력 필드를 채우고 [OK]를 눌러 파일을 생성합니다.

image-20210812124043905


2. XML로 화면 구조 작성

다음과 같이 XML로 화면 구조를 작성하겠습니다.

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:iconSpaceReserved="false">

    <!-- 설정 화면에 보여질 카테고리(기능, 옵션) -->
    <PreferenceCategory
        android:title="기능 설정"
        app:iconSpaceReserved="false">

        <!-- 실제 입력 필드 구성 -->
        <CheckBoxPreference
            android:key="key_add_shortcut"
            android:title="바로가기 아이콘"
            android:icon="@mipmap/ic_launcher"
            android:defaultValue="true"/>

        <SwitchPreference
            android:key="key_switch_on"
            android:title="화면 켜짐"
            android:icon="@mipmap/ic_launcher"
            android:defaultValue="false"/>

    </PreferenceCategory>

    <PreferenceCategory
        android:title="옵션 설정"
        app:iconSpaceReserved="false">

        <!-- 실제 입력 필드 구성 -->
        <EditTextPreference
            android:key="key_edit_name"
            android:title="입력"
            android:summary="이름을 입력하세요"
            android:dialogTitle="이름 입력"
            app:iconSpaceReserved="false"/>

        <!-- ListPreference는 XML로 정의된 목록 데이터가 필요(array.xml) -->
        <ListPreference
            android:key="key_set_item"
            android:title="목록 선택형"
            android:summary="목록"
            android:entries="@array/action_list"
            android:entryValues="@array/action_values"
            android:dialogTitle="목록 선택 제목"
            app:iconSpaceReserved="false"/>

        <PreferenceScreen
            android:title="설정 화면 타이틀"
            android:summary="설정 화면 요약"
            app:iconSpaceReserved="false">
            <intent android:action="android.intent.action.VIEW"
                android:data="https://www.android.com"/>
        </PreferenceScreen>

    </PreferenceCategory>

</PreferenceScreen>


  • 입력 필드의 종류

    위 코드에서 사용한 입력 필드에 대한 설명입니다. 이 외에도 많은 입력 필드들이 정의되어 있습니다.

    이름 설명
    CheckBoxPreference 체크박스 타입의 입력 필드
    SwitchPreference 스위치(On 또는 Off) 타입의 입력 필드
    EditTextPreference 값을 직접 입력하는 타입의 입력 필드
    ListPreference 목록형 입력 필드


2-1. ListPreference에서 사용할 리소스 파일 생성

[res] - [values] 우클릭 - [New] - [Values Resource File] 에서 File name에 ‘array’를 입력하여 array.xml 파일을 생성합니다.

array.xml 파일 안에는 다음과 같이 ListPreference에서 사용할 목록을 정의합니다. 각 태그의 name에 해당하는 부분이 ListPreference의 entries와 entryValues의 값으로 사용됩니다.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- 각 태그의 name에 해당하는 부분이 ListPreference의 entries와 entryValues의 값으로 사용 -->
    <string-array name="action_list">
        <item>action 1</item>
        <item>action 2</item>
        <item>action 3</item>
        <item>action 4</item>
    </string-array>

    <string-array name="action_values">
        <item>value 1</item>
        <item>value 2</item>
        <item>value 3</item>
        <item>value 4</item>
    </string-array>

</resources>


3. PreferenceScreen 뷰를 출력할 SettingFragment 클래스 생성

[java] - 패키지명 우클릭 - [New] - [Kotlin Class/File] 을 클릭하고 입력 필드에 SettingFragment를 입력하여 클래스를 생성합니다.

SettingFragment 클래스는 PreferenceFragmentCompat 추상 클래스를 상속받습니다. 안에 onCreatePreferences( ) 메서드를 오버라이드 해줍니다.

// PreferenceScreen View 삽입
class SettingFragment:PreferenceFragmentCompat() {
    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
    }
}

onCreatePreferences( ) 메서드 안에서는 addPreferencesFromResource( )를 호출합니다.

addPreferencesFromResource 메서드의 파라미터로 PreferenceScreen이 정의된 preference 파일을 전달하면 설정 항목에 대한 View를 자동으로 생성해줍니다.

class SettingFragment:PreferenceFragmentCompat() {
    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        // addPreferencesFromResource에 PreferenceScreen이 정의된 preference 파일 전달
        addPreferencesFromResource(R.xml.preferences)
    }
}

✋ 리소스에 접근하는 형식은 R.리소스디렉터리명.파일명입니다.

4. 레이아웃 파일에 프래그먼트 추가

이제 프래그먼트를 삽입할(뷰를 출력할) 레이아웃 파일에 SettingFragment를 삽입합니다.

[Containers] 카테고리에 있는 ‘FragmentContainerView’ 를 화면에 드래그 하고 SettingFragment를 추가하면 됩니다.

image-20210812140637555

컨스트레인트의 네 방향을 모두 연결하고 layout_width와 layout_height 속성을 모두 ‘match_constraint’로 설정합니다.



[결과 화면]

에뮬레이터를 실행하면 다음과 같이 설정 화면이 구성된 것을 볼 수 있습니다.

image-20210812144413444


[옵션 설정] 의 ‘입력’, ‘목록 선택형’, ‘설정 화면 타이틀’을 클릭하면 각각 아래와 같은 화면이 표시됩니다.

image-20210812150553732



설정 값 사용하기

PreferenceScreen에서 값을 조절하면 설정값이 ‘자동으로 지정된 SharedPreferences 파일’에 저장됩니다.

해당 파일은 ‘레이아웃과 연결된 액티비티 소스코드 파일’에서 PreferenceManager.getDefaultSharedPreferences( ) 메서드를 호출하여 사용할 수 있습니다. 사용법은 일반적인 SharedPreferences 를 사용하는 방법과 동일합니다.

val shared = PreferenceMAnager.getDefaultSharedPreferences(this)

val checkboxValue = shared.getBoolean("key_add_shortcut", false)
val switchValue = shared.getBoolean("key_switch_on", false)
val name = shared.getString("key_edit_name", "")
val selected = shared.getString("key_set_item", "")



정리


  • SharedPreferences는 내부 저장소를 통하여 간단한 데이터(로그인 정보나 앱 설정 정보)를 저장할 수 있는 인터페이스입니다.
  • SharedPreferences에서 값을 저장하고 읽어오는 과정은 다음과 같습니다.
    • 값 저장하기: SharedPreferences 생성하기 ➡ Editor 꺼내기 ➡ putInt, putString 메서드 등으로 값 저장하기 ➡ apply로 파일에 반영하기
    • 값 일어오기: SharedPreferences 생성하기 ➡ getInt, getString 메서드 등으로 값 가져오기
  • SharedPreferences를 위한 설정 화면은 다음의 과정으로 생성합니다.
    • androidx.preferences 의존성 추가 ➡ preferences.xml 파일 생성하고 구조 작성(필요한 리소스 파일도 생성 및 정의) ➡ 뷰를 출력할 프래그먼트 클래스 생성 및 연결 ➡ 뷰를 출력할 레이아웃 파일에 프래그먼트 추가

Categories:

Updated:

Leave a comment