24.01.26 SharedPreferences에 Json타입으로 저장하기

KSang·2024년 1월 29일
0

TIL

목록 보기
41/101

SharedPreferences에 Json타입으로 저장하기

지난 시간에 데이터를 불러오는걸 구현했는데 이제 이미지를 눌렀을때

내 보관함으로 이동시키는 부분이 남았다.

SharedPreferences를 이용하라는데, 내 데이터 모델은

data class SearchModel(
    val thumnail: String,
    val title: String,
    var postType: String,
    val siteName: String,
    val date: String,
    val docUrl: String,
    var bookMark: Boolean = false
): Parcelable

이런식으로 구성 되어있다.

Parcelabe을 저장할순 없고

String으로 일일히 저장시키는것도 매우 비효율적인것 같다

그럴땐 Gson을 이용해 데이터를 Json형식으로 변경시켜주고 저장하면된다.

Repository

class BookmarkRepositoryImpl(context: Context) : BookmarkRepository {
   private val pref = context.getSharedPreferences("MyBox", Context.MODE_PRIVATE)
   private val gson = Gson()
}

프리퍼런스를 관리할 레포지토리를 만들어주자

MyBox란 이름의 SharedPreferences를 만들었다.

이제 이걸 이용해서 데이터를 관리시켜줄 함수를 만들어야 한다.

북마크 작업에서 필요한건 추가 , 제거, 북마크 목록 불러오기, 일반 리스트에서 북마크인지 체크하는 기능이 필요하다

일단 눌렀을때 프리퍼런스에 이미지 데이터를 추가하는 함수를 만들자.

    override fun addBookmark(item: SearchModel) {
        val editor = pref.edit()
        val jsonString = gson.toJson(item)
        editor.putString(item.thumnail, jsonString)
        editor.apply()
    }

프리퍼런스를 수정할 editor를 만들어 주고

프래그먼트에서 받은 item 데이터를 Json 형식으로 변환 시켜줘야한다

Gson을 사용하면 간단하게 만들수 있는데

Gson.toJson으로 Json형식으로 변환 해준뒤

editor를 이용해 프리퍼런스에 Json형식의 데이터를 넣어주고

editor.apply를해 수정 사항을 SharedPreferences 파일에 비동기적으로 적용한다.

SharedPreference에서 apply()는 내부적으로 작업을 백그라운드 스레드에서 수행한다
작업이 완료될때까지 기다려야하는 경우는 commit을 사용하면 됨

나머지 기능들도 추가 해주자

    override fun loadBookmark(): MutableList<SearchModel> {
        val items = mutableListOf<SearchModel>()
        pref.all.forEach { (_, value) ->
            val jsonString = value as String
            val item = gson.fromJson(jsonString, SearchModel::class.java)
            items.add(item)
        }
        return items
    }

    override fun removeBookmark(item: SearchModel): MutableList<SearchModel> {
        val editor = pref.edit()
        editor.remove(item.thumnail)
        editor.apply()
        return loadBookmark()
    }

    override fun checkBookmark(): Map<String,String> {
        val items = mutableMapOf<String,String>()
        pref.all.forEach { (key, value) ->
            val jsonString = value as String
            val item = gson.fromJson(jsonString, SearchModel::class.java)
            items[key] = item.thumnail
        }
        return items
    }

체크북마크 부분은 검색 리스트에서 북마크된 부분을 확인하고 화면에 표시를 해주는 부분인데

빠른 비교를 위해서 매핑해서 만들었다.

여기선 데이터를 동기적으로 관리하는데 아무래도 데이터기도하고 북마크 되는 양이 많아 질수록 속도가 느려질 것이다

class BookmarkRepositoryImpl(context: Context) : BookmarkRepository {
    private val pref = context.getSharedPreferences("MyBox", Context.MODE_PRIVATE)
    private val gson = Gson()
    private var bookmarksCache: MutableList<SearchModel>? = null

    override fun addBookmark(item: SearchModel) {
        val editor = pref.edit()
        val jsonString = gson.toJson(item)
        editor.putString(item.thumnail, jsonString)
        editor.apply()
        bookmarksCache?.add(item)
    }

    override suspend fun loadBookmark(): MutableList<SearchModel> = withContext(Dispatchers.IO) {
        bookmarksCache?.let { return@withContext it }
        val items = mutableListOf<SearchModel>()
        pref.all.forEach { (_, value) ->
            val jsonString = value as String
            val item = gson.fromJson(jsonString, SearchModel::class.java)
            items.add(item)
        }
        bookmarksCache = items
        items
    }

    override suspend fun removeBookmark(item: SearchModel): MutableList<SearchModel> {
        val editor = pref.edit()
        editor.remove(item.thumnail)
        editor.apply()
        bookmarksCache?.removeIf { it.thumnail == item.thumnail }
        return bookmarksCache ?: loadBookmark()
    }


    override fun checkBookmark(): Map<String,String> {
        return pref.all.mapNotNull { (key, value) ->
            val jsonString = value as String
            val item = gson.fromJson(jsonString, SearchModel::class.java)
            item.let { key to it.thumnail }
        }.toMap()
    }
}

캐시를 추가해줘서 북마크가 많아져도 바로바로 표시할수 있게 해주고

loadBookmark를 백그라운드 쓰레드에서 실행시키게 했다.

0개의 댓글