태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

Preferences를 이용한 UI 저장

2009/05/26 00:49

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

이론공부! 으아악!!!



이번 강좌는 이론 공부만 하다가는 도.저.히 답답해서 못 견딜 것만 같아서 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업데이트로 인해 글의 내용과 실제 내용간 차이가 있을 수 있습니다.

저작자 표시 비영리 변경 금지
크리에이티브 커먼즈 라이선스
Creative Commons License

'데이터 관리 > Preferences' 카테고리의 다른 글

Preferences를 이용한 UI 저장  (26) 2009/05/26

커니 데이터 관리/Preferences , , , , ,

  1. Blog Icon
    ABC

    안녕하세요. 포스팅을 보며 따라하다 질문하나 드릴께요.

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

    이 구분 아래 있는 왼쪽에 있는 그림은 무엇인가요?
    저도 어찌하다가 안드로이드 처음 부팅후 같은 화면이 보였던것 같은데 어떻게 발생했는지를
    알고자 한참을 알아보았는데 도무지 알지를 못하겠네요.
    감사합니다.

  2. Messages 화면입니다.
    다른 작업을 해서 어플리케이션이 종료되어도 입력했던 내용은 저장되어있다는 것을 보여주기 위해 에뮬레이터로 가상으로 대화(?)를 나누던 것이죠~ ㅎㅎ

  3. http://www.cyworld.com/embe 제 블로그 입니다. 퍼가겠습니다.^^

  4. Blog Icon
    리바

    궁금합니다... 그럼요.. 프리페어런스 파일은 계속해서 쌓이는건가요??
    파일로 계속 남아있는건가요??
    에뮬이 끝날때 파일도 초기화 되는건가요??

  5. 직접 위에서 생성된 패일을 열어보셔도 알겠지만 내부에 각각 키와 값의 쌍으로 데이터가 저장되어 있으므로 계속 쌓인다기보다는 갱신된다고 봐야죠.

    그리고 파일 형태로 저장되는만큼 삭제하지 않는 이상 초기화되지 않습니다.

  6. Blog Icon
    knoxxr

    강좌 잘 보았습니다.
    이해가 잘 되네요.

  7. 강좌 잘 보고 있습니다. ^^
    글쓰신시 좀 되신것 같은데.. 혹시 아시는 분이 답변을 달아주실까 하고 질문 드려요~


    (안전초보 임을 먼저 말씀 드리고.. ㅠㅠ)

    SharedPreferences 으로 저장한 정보는 어디에 저장이 되는 것일까요?
    어플이 종료되거나 에뮬을 새로 띄워도 계속 저장이 되어 있더군요~

    위 예에서와 같은 화면 정보 뿐 아니라, 간단한 정보들에 대한 저장에 활용 할 수 (신뢰성)있을까 싶어서요.

    관심 갖어 주셔서 감사합니다~ ^^

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

    위 글에 적어놨습니다 :)

  9. Blog Icon
    metLife

    복사해서 실행했는데 has stopped 라는 메세지가 나오네요 왜 저만 안되는거죠.,ㅠㅠ

  10. http://androidhuman.tistory.com/entry/%EB%9F%B0%ED%83%80%EC%9E%84-%EC%97%90%EB%9F%ACRun-time-Error%EC%97%90-%EB%8C%80%EC%B2%98%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95

    찾아보시고 에러 메시지를 확인해보세요.

  11. Blog Icon
    궁금이

    안녕하세요. 항상 개발할 때 참고하면서 보고 있는데,

    혹시sharedPreference를 사용하여 List상태도 저장해 놀 수 있나요 ?
    ListView화면에서 전화가 온다든지, Home에 갔다오면
    라벨아래로는 전부 하얗게 되버리는데..
    sharedPreference를 사용해서 고쳐질까요 ?

  12. 하얕게 된다는게 정확히 어떤 걸 말씀하시는건지요??
    리스트뷰에 들어가있던 데이터가 모두 사라진다는 걸 말씀하시는건가요?

    DB를 사용하지 않는 경우라면 액티비티가 전환되면서 데이터들이 사라질 수 있습니다. 생애주기 메소드를 참고하셔서 적절히 처리를 해 주셔야 합니다.

  13. Blog Icon
    참치

    sharedPreference를 사용해서 이미지를 저장 할 순 없나요?
    이미지를 끌어와서 특정 위치에 넣고 저장 하고 싶은데
    저장이 되질 않네요..

  14. Blog Icon
    조우리

    아.. 체크 한 후에 DDMS로 바로 멈추게 했더니 저장이 안되더군요. 먼저 onStop을 불러주는 행위를 한 후에 DDMS로 멈추니까 잘 동작하네요. 항상 잘 보고 있습니다. 감사합니다 ㅎ

  15. Blog Icon
    a

    항상 감사합니다

  16. Blog Icon
    ^^

    우왕ㅋ굳ㅋ
    ㅋㅋ^^ 좋은 정보 고맙습니다!
    담아갈게요~

  17. Blog Icon
    ^^9

    잘보고 가요 ^^

  18. Blog Icon
    ba

    감사합니다. 덕분에 쉽게 해결했어요..^^

  19. Blog Icon
    w

    그럼 이렇게 저장하면은 나중에 프린트 할때 그대로 나오나요?

  20. Blog Icon
    nick

    Preference가 어디 저장되어 있는지 완전 삽질하며 찾다가 좋은 정보 보고 갑니다^^
    감사합니다~*

  21. 좋은글 출처를 표시하고 블로그에 담아갑니다. ^^

  22. Blog Icon
    부개동

    질문있습니다. 저렇게 체크박스나 에딧텍스트 같은경우는 많은예제들이 있는데
    이미지뷰나 버튼에 대한 예제가 없어서요..
    이미지 버튼의 이미지 변화에 대한 저장과 이미지뷰의 이미지 변화가 있을시 저장은 어떻게해야할까요?

  23. 이미지버튼이나 이미지뷰에 변화가 있을 경우에는 Preference를 사용하기보단 아예 다른 방법 (onSaveInstanceState()에 이미지 정보를 임시로 저장하는 로직 삽입)을 사용해야 할 것으로 보입니다.

  24. Blog Icon
    드로이드초보자

    많은 도움 받고 있습니다. 정말 감사합니다 .ㅎㅎ
    코딩하다 문뜩 질문할 것이 생겼습니다 ㅎㅎ
    제가 잠금어플을 만들고 있는데 패키지명을 통해 잠그고 잇습니다.
    이 잠금처리된 어플들을 관리하기 위해 패키지명들을 Preferences를 통해서 저장하고 그 목록들을 불러오고 싶은데
    방법이 없을까요 ... ?

  25. Preference로 문자열 집합(Set)을 저장할 수 있습니다.
    public abstract SharedPreferences.Editor putStringSet (String key, Set<String> values)

    하지만, Preference 보다는 데이터베이스를 사용하는 쪽이 조금 더 목록을 효율적으로 관리하기에는 용이해 보입니다.