저 같은 경우는 앱 설정에서 설정된 정보를 SharedPreference에 담을 수 있도록 프로그램을 짜는 경우가 종종 있었습니다. 맨날 String, Int와 같은 자료만 담다가 ArrayList를 담을 일이 생겼는데, 기본적으로 SharedPreference에 ArrayList를 담을 방법은 존재하지 않았습니다.
해결 방법은 간단했습니다.
정보를 저장할 때는 (set) : ArrayList 데이터를 JSON 데이터로 변환 후, 그 정보를 String으로 저장
정보를 받아올 때는 (get) : String으로 저장된 JSON 데이터를 하나씩 꺼내와서 ArrayList로 저장 후 반환
즉, JSON 데이터 형식을 매개로 ArrayList와 String의 자유로운 변환을 통해 값을 만질 수 있는 것입니다.
다음은 예제입니다.
String 관련 예제도 추가로 넣었으니 비교하면서 보시면 됩니다.
1. String getter와 setter 및 ArrayList getter와 setter
class SharedPreference(context: Context) {
val preference: SharedPreferences = context.getSharedPreferences("preference", 0)
// String 조작하는 SharedPreference
var stringPreference: String
get() = preference.getString("stringPreference", "default value")!!
set(value) = preference.edit().putString("stringPreference", value).apply()
// ArrayList 조작하는 SharedPreference
var arrayListPreference: ArrayList<String>
get() {
// JSON 데이터를 String으로 저장했으므로, String의 값을 받아옵니다.
val json = preference.getString("arrayListPreference", null)
val arrayList = ArrayList<String>() // 반환 할 arrayList를 만들어줍니다.
if(json != null) {
try {
val jsonArray = JSONArray(json) // JSONArray로 저장했던 값을 변환합니다.
// JSON의 값들을 하나씩 arrayList로 옮깁니다.
for(i in 0 until jsonArray.length()) arrayList.add(jsonArray.optString(i))
} catch(e: JSONException) {
e.printStackTrace()
}
}
// arrayList를 반환합니다.
return arrayList
}
// 여기서 values는 arrayList입니다.
set(values) {
val editor = preference.edit()
val jsonArray = JSONArray() // JSONArray를 미리 만들어주고
for(value in values) {
jsonArray.put(value) // arrayList의 값들을 JSONArray에 넣어줍니다.
}
if(values.isNotEmpty()) {
// 비어있는 ArrayList가 아니라면 JSON으로 변환된 값을 String으로 바꾸어 SharedPreference로 저장합니다.
editor.putString("arrayListPreference", jsonArray.toString())
} else {
editor.putString("arrayListPreference", null)
}
editor.apply()
}
}
2. App class
class App: Application() {
companion object {
lateinit var preference: SharedPreference
}
override fun onCreate() {
preference = SharedPreference(applicationContext)
super.onCreate()
}
}
3. Manifest에 .App 추가
..
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
../>
<application
android:name=".App"
android:allowBackup="true"
..>
<activity android:name=".MainActivity"..
</manifest>
4. 테스트 레이아웃 구성 (activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="24dp"
tools:context=".MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="String Test"
android:textSize="20sp"
android:gravity="center"/>
<EditText
android:id="@+id/string_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="문자열을 입력해주세요." />
<Button
android:id="@+id/string_set"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="SharedPreference String 저장하기"
android:textAllCaps="false"/>
<TextView
android:id="@+id/string_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:gravity="center"/>
<Button
android:id="@+id/string_get"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="SharedPreference String 불러오기"
android:textAllCaps="false"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ArrayList Test"
android:textSize="20sp"
android:gravity="center"
android:layout_marginTop="48dp"/>
<EditText
android:id="@+id/arraylist_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="문자열을 입력해주세요." />
<Button
android:id="@+id/arraylist_set"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="SharedPreference ArrayList 저장하기"
android:textAllCaps="false"/>
<TextView
android:id="@+id/arraylist_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:gravity="center"/>
<Button
android:id="@+id/arraylist_get"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="SharedPreference ArrayList 불러오기"
android:textAllCaps="false"/>
</LinearLayout>
5. MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// String Test
// set
string_set.setOnClickListener {
App.preference.stringPreference = string_input.text.toString()
}
// get
string_get.setOnClickListener {
string_text.text = App.preference.stringPreference
}
// ArrayList Test
// set
arraylist_set.setOnClickListener {
// , 를 기준으로 문자열을 나누어 ArrayList로 만들어줍니다.
val arrayList = arraylist_input.text.split(",") as ArrayList<String>
App.preference.arrayListPreference = arrayList
}
// get
arraylist_get.setOnClickListener {
// ArrayList로 값을 받아온 뒤, 각 원소의 인덱스와 값을 TextView에 순서대로 띄웁니다.
val arrayList = App.preference.arrayListPreference
val builder = StringBuilder()
for((index, value) in arrayList.withIndex()) {
builder.append("$index: $value, ")
}
arraylist_text.text = builder.toString()
}
}
}
테스트 화면