SharedPreferences를 json 포맷으로 관리하기

이번 포스팅에서는 SharedPreferences에 복잡한 형태의 데이터를 json 포맷으로 저장하고 불러오는 법에 대해 알아보도록 하겠습니다.

SharedPreferences는 Key-Value 형태로 이루어진 딕셔너리를 저장하도록 설계된 저장장소인데요, 이 Value 부분에 json으로 구성된 긴 형태의 데이터를 저장함으로써 복잡한 형태의 데이터도 저장할 수가 있습니다.

이 때 앱 안의 데이터를 json으로 Serialize하고 다시 복원하는 Deserialize를 편하게 실행하게 해 주는 Gson이라는 라이브러리가 있습니다. 이번 포스팅에서는 이 라이브러리를 활용하겠습니다.

여기서는 Data class 이해하고 RecyclerView에서 사용하기 강의에서 만들었던 프로젝트를 수정하면서 구현해보겠습니다.

라이브러리 추가

우선 Gson을 디펜던시에 추가합니다.

1
2
3
dependencies {
    implementation 'com.google.code.gson:gson:2.8.6'
}

화면 구성

다음은 로딩에 사용할 플로팅버튼을 화면에 추가해줍니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<androidx.constraintlayout.widget.ConstraintLayout
    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/button_load"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="20dp"
        android:layout_marginBottom="20dp"
        android:clickable="true"
        android:focusable="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:srcCompat="@android:drawable/ic_menu_add" />
</androidx.constraintlayout.widget.ConstraintLayout>

Key 준비

SharedPreferences에서는 데이터를 다룰때 키를 사용하므로 그때 사용할 키를 정의해줍니다. 평범하게 SharedPreferences를 이용하는 경우에는 각 밸류마다 서로다른 키를 지정해야하므로 많은 키를 지정해야 하는데 여기서는 모든 데이터를 뭉뚱그려서 하나의 키에 저장할 것이므로 데이터용 키는 하나만 만들면 됩니다.

1
2
3
4
companion object {
    private const val KEY_PREFS = "shared_preferences"
    private const val KEY_DATA = "monster_data"
}

savePref() 작성

다음은 데이터를 저장하는 함수를 만듭니다. 이미 SharedPreferences로 앱 설정값 저장하고 불러오기강의에서 설명했던 방식과 유사한데요, gson을 사용하면 gson 인스턴스를 만들고, 그 인스턴스를 이용해서 데이터를 json으로 변환하는 작업이 추가됩니다. Recyclerview 어댑터 안의 데이터는 private를 떼어서 다른 클래스에서도 접근할수 있도록 합니다.

1
2
3
4
5
6
7
8
9
private fun savePref() {
    val sharedPreferences = getSharedPreferences(KEY_PREFS, Context.MODE_PRIVATE)
    val editor = sharedPreferences.edit()
    val gson = Gson()
    val json = gson.toJson(rvAdapter.dataSet)
    editor.putString(KEY_DATA, json)
    editor.apply()
    Log.d("debug", "Data saved")
}

loadPref() 함수 작성

이번엔 데이터를 불러오는 함수를 만듭니다. 기존의 방법과 역시 동일한데, TypeToken을 적용해서 데이터를 복원하는 부분이 추가되었습니다. json으로 SharedPreferences에 저장하는 순간 데이터가 가지고 있는 타입정보가 모두 사라지기 때문에 데이터를 복원하면서 타입정보를 다시 부여하기 위해 타입토큰을 사용합니다. 여기서는 <<ArrayList<Monster>>라는 타입을 만들어서 데이터에 부여해 줍니다. 그리고 Recyclerview 어댑터 안의 데이터는 변경가능하도록 var 로 변경해줍니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
private fun loadPref() {
    val sharedPreferences = getSharedPreferences(KEY_PREFS, Context.MODE_PRIVATE)
    if (sharedPreferences.contains(KEY_DATA)) {
        val gson = Gson()
        val json = sharedPreferences.getString(KEY_DATA, "")
        try {
            val typeToken = object : TypeToken<ArrayList<Monster>>() {}.type
            rvAdapter.dataSet = gson.fromJson(json, typeToken)
        } catch (e: JsonParseException) {
            e.printStackTrace()
        }
        Log.d("debug", "Data loaded")
    }
}

함수 실행

다음은 메인액티비티 안에서 savePrefloadPref를 실행시키면 됩니다. loadPref를 실행하고 어댑터에 데이터 변경을 알려주면 됩니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
override fun onCreate(savedInstanceState: Bundle?) {
    binding.buttonLoad.setOnClickListener {
        loadPref()
        rvAdapter.notifyItemChanged(0, rvAdapter.dataSet.size)
    }
}

override fun onStop() {
    super.onStop()
    savePref()
}

이렇게 SharedPrefenrences와 Gson을 이용해서 복잡한 데이터를 json으로 저장하고 불러오는 법에 대해 알아보았습니다.

Built with Hugo
Theme Stack designed by Jimmy