본문 바로가기

데이터 관리/Preferences

Preferences를 이용한 UI 저장

오래간만에 강좌로 찾아뵙습니다.
그동안 미진했던 이론공부(..)를 한답시고 오랫동안 잠수좀 탔는데요, 역시나 이론공부는 지겹기만 합니다!
하지만, 더 나은 내일(?)을 위해서는 어쩔 수 없기에 눈물을 머금고 당분간은 이론 공부를 해야 하네요..ㅠㅠ

이론공부! 으아악!!!



이번 강좌는 이론 공부만 하다가는 도.저.히 답답해서 못 견딜 것만 같아서 Preference에 대해 실습해본 내용을 바탕으로 하였습니다. 요즘 주로 보는 것이 "데이터 저장" 부분이라 Preference 쪽을 먼저 다루게 되네요.

자, 그럼... 슬슬 시작해봅시다.

우선, Preference가 무엇인가?에 대한 고찰(너무 거창한가요?)부터 들어가보도록 하겠습니다.
사실, Preference의 정확한 명칭은 Shared Preference로 직역하면 "공유된 선호(?)" 정도가 되는데.....음... 사실, Preference 자체가 사전 자체의 의미보다는, 프로그램 등에서의 Preferences 쪽에 더 가깝다고 보시면 됩니다. (이클립스에도 Preference 메뉴가 있죠?) 고로, "개인 설정" 정도의 의미로 해석하면 적절합니다.

그렇다면, 이 Shared Preferences는 왜 있는 것일까요? 데이터의 저장이야 파일이나 데이터베이스(SQLite)를 이용하면 될텐데요? - 네, 맞습니다. Shared Preference는 데이터의 저장보다는 UI 상태를 저장하는데 사용됩니다.

UI상태를 저장한다구요? 그걸 왜 저장하는데요? 그럴 필요가 있나요?
- 네, 그렇습니다. 안드로이드 액티비티의 라이프사이클을 아신다면, UI 저장은 필수요소라는걸 쉽게 느끼실 수 있을겁니다. 안드로이드 액티비티의 라이프사이클에 대해 잘 모르시는 분은 2008/11/30 - [안드로이드 이야기/안드로이드 입문] - #03. Hello, Android!로 배우는 기초 - (3) Activity 집중공략 을 참조하세요.

간단하게 말하면, 안드로이드가 모바일 기기를 주 목적으로 하다보니, 메모리가 부족할 경우 메모리에 올라와있는 것들을 지맘대로 종료시킬 가능성이 허다합니다. 만약, 메시지를 입력하다가 전화가 와서 전화를 받았는데 마침 다른 어플리케이션들이 너무 많이 실행되고 있어서 메시지 어플리케이션이 강제종료되었다고 생각해봅시다. 지금까지 입력했던 메시지는 다 날아가버리는 걸까오? - 그래선 안 됩니다. 암.

그리고, 어플리케이션 중 특정 설정을 저장해야 하는 경우가 있습니다. 메신저를 예로 들면 자동 로그인, 비밀번호 저장 여부 설정 등이 되겠지요? 이러한 설정들도 Shared Preferences를 이용하여 저장됩니다.

이렇게, 액티비티 및 어플리케이션이 메모리 부족 등에 인해 종료된 후, 사용자가 다시 그 어플리케이션을 실행시켰을 때 종료되기 전 모습 그대~로 다시 복구시켜주는 역할을 바로 Shared Preferences를 이용해 해줄 수 있습니다.

이번 강좌를 통해 만들어볼 예제 어플리케이션의 모습입니다. EditText 필드 하나와 체크박스 2개로 구성된 간단한 어플리케이션입니다.



레이아웃 : main.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<EditText android:layout_height="wrap_content"
 android:id="@+id/EditText"
 android:hint="글자를 입력하세요!"
 android:layout_width="fill_parent">
 </EditText>

<CheckBox android:id="@+id/CheckBox01"
 android:text="체크박스1"
 android:layout_height="wrap_content"
 android:layout_width="fill_parent">
</CheckBox>

<CheckBox android:id="@+id/CheckBox02"
 android:layout_height="wrap_content"
 android:text="체크박스2"
 android:layout_width="fill_parent">
</CheckBox>


코드 : prefExample.java

package com.androidhuman.Preferences;

import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.CheckBox;
import android.widget.EditText;

public class prefExample extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        SharedPreferences pref = getSharedPreferences("pref", Activity.MODE_PRIVATE); // Shared Preference를 불러옵니다.
        EditText edit1 = (EditText)findViewById(R.id.EditText);
    	CheckBox check1 = (CheckBox)findViewById(R.id.CheckBox01);
    	CheckBox check2 = (CheckBox)findViewById(R.id.CheckBox02);
    	
               // 저장된 값들을 불러옵니다.
    	String text = pref.getString("editText", "");
    	Boolean chk1 = pref.getBoolean("check1", false);
    	Boolean chk2 = pref.getBoolean("check2", false);
    	
    	edit1.setText(text);
    	check1.setChecked(chk1);
    	check2.setChecked(chk2);
    }
    
    public void onStop(){ // 어플리케이션이 화면에서 사라질때
    	super.onStop();
    	SharedPreferences pref = getSharedPreferences("pref", Activity.MODE_PRIVATE); // UI 상태를 저장합니다.
    	SharedPreferences.Editor editor = pref.edit(); // Editor를 불러옵니다.
    	
    	EditText edit1 = (EditText)findViewById(R.id.EditText);
    	CheckBox check1 = (CheckBox)findViewById(R.id.CheckBox01);
    	CheckBox check2 = (CheckBox)findViewById(R.id.CheckBox02);
    	
                // 저장할 값들을 입력합니다.
    	editor.putString("editText", edit1.getText().toString());
    	editor.putBoolean("check1", check1.isChecked());
    	editor.putBoolean("check2", check2.isChecked());
    	
    	editor.commit(); // 저장합니다.
    }
}

이 어플리케이션의 목적, SharedPreferences을 사용하는 목적은 "액티비티를 종료시켜도 사용자는 모르게" 하는 것입니다.
액티비티 라이프사이클에 따라서, 액티비티가 종료될 때 당시 UI상태를 기억하고 있다가 사용자가 다시 그 액티비티 (어플리케이션)을 실행시킬 때 저장된 상태를 그대~로 불러와서, 마치 사용자는 "아무 일도 일어나지 않은 것처럼" 계속 작업을 할 수 있죠.

일단, Shared Preferences가 어떻게 생긴 놈인지부터 알아보겠습니다.
Shared Preferences는 예전 Intent에 정보를 넣어서 보낼 때 처럼 키(key)와 값(Value) 한 쌍으로 이루어져 있습니다. 


자, 그럼 이제부터 Shared Preferences를 이용하여 데이터를 저장하는 과정에 대해 알아봅시다.

1. Shared Preferences 객체 생성하기
Intent 객체를 만들고, 그 안에 필요한 데이터를 넣어 보냈던 것 처럼 Shared Preferences 또한 객체를 생성해 주어야 합니다.

// "pref"라는 가진 Shared Preferences 객체를 생성합니다.
SharedPreferences pref = getSharedPreferences("Pref", Activity.MODE_PRIVATE);


2. Shared Preferences를 수정할 수 있는 에디터 생성 및 편집
SharedPreferences 겍체를 수정하려면, Editor 객체를 받아와야 합니다.

SharedPreferences.Editor editor = pref.edit(); // 에디터를 받아옵니다.
EditText edit1 = (EditText)findViewById(R.id.EditText);
CheckBox check1 = (CheckBox)findViewById(R.id.CheckBox01);
CheckBox check2 = (CheckBox)findViewById(R.id.CheckBox02);
    	
editor.putString("editText", edit1.getText().toString()); // 데이터를 입력합니다.
editor.putBoolean("check1", check1.isChecked());
editor.putBoolean("check2", check2.isChecked());
    	
editor.commit(); // 편집을 종료하고 저장합니다.
 SharedPreferences에서의 데이터 입력도 put<Type> (_키_, _값_) 형식을 따르고 있습니다.
사용 가능한 메소드로는 putString, putInt, putLong, putFloat, putBoolean이 있습니다. 이 형식에 맞추어 입력한 후, commit()메소드를 이용하여 데이터 편집을 마치고 저장합니다.

이 과정은 액티비티가 종료되는 과정, 즉 onStop()에서 일어나기에 onCreate()메소드를 오버라이드 하는 것처럼 onStop()메소드를 오버라이딩해야 합니다. onStop()메소드를 오버로딩하면 다음과 같이 됩니다.

public void onStop(){
    	super.onStop();
    	SharedPreferences pref = getSharedPreferences("pref", Activity.MODE_PRIVATE);
    	SharedPreferences.Editor editor = pref.edit();
    
    	
    	EditText edit1 = (EditText)findViewById(R.id.EditText);
    	CheckBox check1 = (CheckBox)findViewById(R.id.CheckBox01);
    	CheckBox check2 = (CheckBox)findViewById(R.id.CheckBox02);
    	
    	editor.putString("editText", edit1.getText().toString());
    	editor.putBoolean("check1", check1.isChecked());
    	editor.putBoolean("check2", check2.isChecked());
    	
    	editor.commit();
    }

저장하는 것은 배웠으니, 이제 불러오는 것을 배워야겠죠?
불러오는 것은 그리 어렵지 않습니다. 아까 저장한 SharedPreferences 객체로부터 저장된 UI정보를 불러오기만 하면 됩니다.
public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        SharedPreferences pref = getSharedPreferences("pref", Activity.MODE_PRIVATE);
        EditText edit1 = (EditText)findViewById(R.id.EditText);
    	CheckBox check1 = (CheckBox)findViewById(R.id.CheckBox01);
    	CheckBox check2 = (CheckBox)findViewById(R.id.CheckBox02);
    	
    	edit1.setText(pref.getString("editText", ""));
    	check1.setChecked(pref.getBoolean("check1", false));
    	check2.setChecked(pref.getBoolean("check2", false));
    }

아까 데이터를 저장할 때는 putExtra()를 썼던 것과 달리 데이터를 받아올 떄에는 get<Type> 메소드를 쓰면 됩니다.
get<Type> 메소드의 원형은 get<Type>(_키_, _기본값_) 입니다. 일단 키에 해당하는 데이터를 찾지만, 없을 경우엔 두번째 파라미터에 들어간 내용으로 초기화되게 됩니다.

이렇게 만들었으면, 한번 테스트 해봐야겠죠?
어플리케이션을 로드한 후, 글씨도 입력해보고 체크박스에도 표시해 봅니다.



DDMS를 이용하여 임의로 프로세스를 종료시켜보도 되고,  저처럼 혼자 놀다가(?) 다시 어플리케이션을 실행해보세요. 아까 입력한 내용이 사라지지 않고 고대~로 있음을 확인할 수 있습니다.

우왕ㅋ굳ㅋ


이렇게, Shared Prefernces에 대한 설명을 마치겠습니다.
Shared Prefence는 그다지 어렵지 않으니 다양하게 연습해보세요~

*추가내용 : 2009/05/26
SharedPreference는 어떤 식으로 저장될까요? 파일? 데이터베이스?
정답은 파일입니다. DDMS를 통해 data/data/패키지이름/shared_prefs 폴더에 위에서 지정한 Preferences의 이름으로 저장됩니다.




이 글은 Android SDK 1.5_r1을 기준으로 작성되었습니다.
추후 SDK업데이트로 인해 글의 내용과 실제 내용간 차이가 있을 수 있습니다.