SharedPreferences란 무엇인가?
ArrayList를 SharedPreferences에 저장하는 예제를 살펴보기 전에, 먼저 Android에서 SharedPreferences가 어떤 역할을 하는지 이해할 필요가 있습니다. SharedPreferences는 키(Key)와 값(Value) 쌍 형태로 간단한 데이터를 영구적으로 저장하거나 불러올 수 있게 해주는 경량 저장소입니다.
SharedPreferences에는 다음과 같은 주요 메서드가 제공됩니다.
edit() — SharedPreferences의 값을 편집할 수 있는 Editor 객체를 반환합니다.
commit() — 편집된 값을 XML 파일에 동기적으로 즉시 저장합니다.
apply() — Editor의 변경 사항을 백그라운드에서 비동기적으로 SharedPreferences에 반영합니다.
remove(String key) — 지정한 키와 해당 값을 SharedPreferences에서 삭제합니다.
put() — 키와 값의 쌍을 SharedPreferences XML 파일에 저장합니다.
SharedPreferences의 기본적인 사용 문법은 아래와 같습니다.
final SharedPreferences sharedPreferences = getSharedPreferences("USER",MODE_PRIVATE);위 코드에서는 "USER.xml"이라는 이름의 SharedPreferences 파일을 생성했습니다. 두 번째 인자인 MODE_PRIVATE는 해당 SharedPreferences가 비공개 모드로 생성되어 다른 애플리케이션에서 접근할 수 없음을 의미합니다.
이제 실제 예제를 통해 Android에서 SharedPreferences를 사용하는 방법을 단계별로 알아보겠습니다.
구현 단계
1단계 — 프로젝트 생성
Android Studio에서 새 프로젝트를 생성합니다. 상단 메뉴에서 File → New Project를 선택한 후, 새 프로젝트 생성에 필요한 모든 세부 정보를 입력하세요.
2단계 — 레이아웃 작성
res/layout/activity_main.xml 파일에 다음 코드를 추가합니다.
<?xml version = "1.0" encoding = "utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android = "https://schemas.android.com/apk/res/android"
xmlns:app = "https://schemas.android.com/apk/res-auto"
xmlns:tools = "https://schemas.android.com/tools"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:orientation = "vertical"
tools:context = ".MainActivity"
tools:layout_editor_absoluteY = "81dp">
<EditText
android:id = "@+id/name"
android:layout_width = "match_parent"
android:layout_height = "60dp"
android:layout_marginTop = "8dp"
android:autofillHints = ""
android:hint = "NAME"
app:layout_constraintTop_toTopOf = "parent"
tools:layout_editor_absoluteX = "0dp" />
<EditText
android:id = "@+id/address"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_marginTop = "84dp"
android:hint = "Phone Number"
android:importantForAutofill = "no"
android:inputType = ""
app:layout_constraintTop_toTopOf = "@+id/name"
tools:layout_editor_absoluteX = "16dp"
tools:targetApi = "o" />
<Button
android:id = "@+id/button"
android:layout_width = "108dp"
android:layout_height = "wrap_content"
android:layout_marginStart = "8dp"
android:layout_marginLeft = "8dp"
android:layout_marginTop = "120dp"
android:layout_marginEnd = "8dp"
android:layout_marginRight = "8dp"
android:gravity = "center_horizontal"
android:text = "Save"
app:layout_constraintEnd_toEndOf = "parent"
app:layout_constraintHorizontal_bias = "0.503"
app:layout_constraintStart_toStartOf = "parent"
app:layout_constraintTop_toTopOf = "@+id/address" />
<Button
android:id = "@+id/read"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_marginStart = "8dp"
android:layout_marginLeft = "8dp"
android:layout_marginTop = "88dp"
android:layout_marginEnd = "8dp"
android:layout_marginRight = "8dp"
android:gravity = "center_horizontal"
android:text = "read"
app:layout_constraintEnd_toEndOf = "parent"
app:layout_constraintStart_toStartOf = "parent"
app:layout_constraintTop_toBottomOf = "@+id/button" />
<TextView
android:id = "@+id/result"
android:layout_width = "wrap_content"
android:layout_height = "0dp"
android:layout_marginStart = "8dp"
android:layout_marginLeft = "8dp"
android:layout_marginTop = "184dp"
android:layout_marginEnd = "8dp"
android:layout_marginRight = "8dp"
android:text = "result"
app:layout_constraintEnd_toEndOf = "parent"
app:layout_constraintStart_toStartOf = "parent"
app:layout_constraintTop_toBottomOf = "@+id/button" />
</android.support.constraint.ConstraintLayout>위 레이아웃 XML에는 이름(name)과 주소(address)를 입력받기 위한 두 개의 EditText가 포함되어 있습니다. 사용자가 Save 버튼을 누르면 입력값들이 배열 형태로 SharedPreferences에 저장되고, read 버튼을 누르면 SharedPreferences에 저장된 배열에서 값을 다시 읽어와 화면에 표시합니다.
3단계 — MainActivity 구현
src/MainActivity.java 파일에 다음 코드를 추가합니다.
package com.example.andy.myapplication;
import android.annotation.SuppressLint;
import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ArrayList<String> arrPackage;
setContentView(R.layout.activity_main);
final SharedPreferences sharedPreferences = getSharedPreferences("USER",MODE_PRIVATE);
final EditText name = findViewById(R.id.name);
final EditText address = findViewById(R.id.address);
final TextView result = findViewById(R.id.result);
Button save = findViewById(R.id.button);
Button read = findViewById(R.id.read);
arrPackage = new ArrayList<>();
read.setOnClickListener(new View.OnClickListener() {
@SuppressLint("LongLogTag")
@Override
public void onClick(View v) {
Gson gson = new Gson();
String json = sharedPreferences.getString("Set", "");
if (json.isEmpty()) {
Toast.makeText(MainActivity.this,"There is something error",Toast.LENGTH_LONG).show();
} else {
Type type = new TypeToken<List<String>>() {
}.getType();
List<String> arrPackageData = gson.fromJson(json, type);
for(String data:arrPackageData) {
result.setText(data);
}
}
}
});
save.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(name.getText().toString().isEmpty() && address.getText().toString().isEmpty()) {
Toast.makeText(MainActivity.this,"Plz Enter all the data",Toast.LENGTH_LONG).show();
}else{
String nameData = name.getText().toString().trim();
String addressData = address.getText().toString().trim();
arrPackage.add(nameData);
arrPackage.add(addressData);
Gson gson = new Gson();
String json = gson.toJson(arrPackage);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("Set",json );
editor.commit();
}
}
});
}위 코드의 핵심은 ArrayList를 GSON(JSON 문자열)으로 변환한 후, 이를 문자열 형태로 SharedPreferences에 저장하는 것입니다. 반대로 값을 읽어올 때는 저장된 JSON 문자열을 다시 List 객체로 역직렬화(deserialize)하여 사용합니다.
4단계 — GSON 라이브러리 추가
GSON을 사용하려면 build.gradle 파일에 GSON 라이브러리 의존성을 추가해야 합니다.
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.andy.myapplication"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'5단계 — 앱 실행
manifest.xml은 수정할 필요가 없습니다. 이제 애플리케이션을 실행해 보겠습니다.
실제 Android 기기를 컴퓨터에 연결했다고 가정합니다. Android Studio에서 프로젝트의 액티비티 파일 중 하나를 연 뒤, 툴바의 Run 아이콘을 클릭하세요. 실행 옵션 목록에서 본인의 모바일 기기를 선택하면, 모바일 화면에 기본 화면이 표시됩니다.

위 예제에서는 이름과 주소를 입력한 후 Save 버튼을 클릭했습니다.

위 예제에서는 read 버튼을 클릭했습니다. 그러면 SharedPreferences에 저장된 값이 TextView에 표시되는 것을 확인할 수 있습니다.
마무리
이처럼 SharedPreferences는 기본적으로 문자열, 숫자 등의 원시 타입만 지원하지만, GSON 라이브러리를 활용해 ArrayList나 사용자 정의 객체를 JSON 문자열로 직렬화하면 손쉽게 저장하고 불러올 수 있습니다. 소량의 리스트 데이터를 앱 내에 영구 보관할 때 유용하게 활용할 수 있는 패턴이니 꼭 익혀두세요.