ArrayList vs MutableList, 직렬화(serialization), GSON, Shared Preference

임현주·2021년 11월 5일
0
post-thumbnail

시작

혼자 공부하면서 정리하고 싶은 부분을 작성한 글입니다 👀
함께 공부하는 사람에게는 도움이 되었으면 좋겠고,
혹시 제가 잘못 이해한 부분이 있다면 알려주시면 감사하겠습니다 💌


🔹 ArrayList vs MutableList

  • List : 읽기 전용 리스트 (readOnly), 데이터가 변경될 일 없으면 사용 권장
  • MutableList : 수정 가능한 리스트
  • ArrayList : 내부가 Array(배열) 형태로 되어있는 수정 가능한 리스트

List와 MutableList의 차이점은 명확해서 확실히 알겠다만.. 사실 MutableList는 내게 넘 생소하다🙉 대체 ArrayList와 MutableList의 차이가 뭘까...

ArrayList는 MutableList 인터페이스를 구현하는 클래스이고, mutableListOf() 와 arrayListOf() 모두 ArrayList를 반환한다.

@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun <T> mutableListOf(): MutableList<T> = ArrayList()

@SinceKotlin("1.1")
@kotlin.internal.InlineOnly
public inline fun <T> arrayListOf(): ArrayList<T> = ArrayList()

일반적으로 MutableList가 좀 더 추상화되어 있어서 아무 '가변 리스트'에 맞기 때문에 사용을 권장한다고 한다. 하지만 내가 지금 ArrayList를 쓰는 것이 적합하다고 판단되면 (절대 형변환할 일이 없는 경우 등) 굳이 MutableList를 사용할 이유는 없다. MutableList는 클래스가 아니라 인터페이스이기 때문에 직접 실제 인스턴스를 만들 수 없기 때문이다.

public interface MutableList<E> : List<E>, MutableCollection<E> {
...
}

🔹 직렬화(serialization)

추상적인 객체를 구체적이고 저장 및 전송 가능한 단순한 텍스트 파일, 연속된 byte 정보 등으로 바꾸는 것. 쉽게 말해 객체를 다른 환경에 저장했다가 나중에 재구성할 수 있도록 만드는 과정을 말한다 😀 (역직렬화는 반대!)

언제 쓸까 ❓

객체의 상태를 영속해야 할 필요가 있을 때 (ex. 게임을 다시 시작했을 때, 종료했던 시점부터 다시 가능한 경우), 정보를 전달할 필요가 있을 때, API나 데이터를 변환하여 추출할 때 사용한다.

API 공부하다가 만난 'Parcel: unable to marshal value~' 오류. 발생 지점은 인텐트로 다음 액티비티에 json 데이터 ArrayList를 넘겨주는 부분이다. 번들을 통해 직렬화 가능한 데이터를 전달할 때는 전달하는 데이터가 직렬화 가능하게 인터페이스를 구현해 주어야 한다. 아래와 같이 Serializable만 적어주면 해결된다.

//data class는 생성자를 바로 만들 수 있다 (메소드를 만들지 않아도)
data class Photo(
    var thumbnail: String?,
    var author: String?,
    var createdAt: String?,
    var likesCount: Int?
) : Serializable {
}

🔹 GSON

객체를 JSON으로, 또는 JSON을 객체로 변환을 도와주는 구글의 JSON 라이브러리.

JSON은 JVM 언어에 정의되어 있는 타입이 아니기 때문에 별도의 변환 작업과 파싱을 해주어야 한다(직렬화, 역직렬화). Gson의 converter를 이용하면 data class 객체에 jsonObject key 값을 각각 매핑하지 않아도 바로 객체를 생성할 수 있다. 단, data class의 변수 이름과 키값이 동일해야 제대로 값이 들어갈 수 있다.

  • 직렬화(serialization) 예시
// 매개변수로 들어온 배열 -> 문자열 변환
val searchHistoryListString: String = Gson().toJson(searchHistoryList)
  • 역직렬화(deserialization) 예시
// 매개변수로 들어온 배열 -> 문자열 변환
storedSearchHistoryList = Gson().fromJson(storedSearchHistoryListString, Array<SearchData>::class.java)
                                .toMutableList() as ArrayList<SearchData>

🔹 Shared Preference

  • shared
    안드로이드에서 지원하는 로컬 데이터베이스 저장 관리 시스템 - DBMS(Data Base Management System)
    사용자가 앱을 이용하며 만들어지는 데이터를 저장할 수 있음

  • shared preference
    안드로이드에서 앱의 데이터를 key-value의 형태로 저장하는 방식

아래는 '최근 검색어 저장 기능'을 구현하면서 작성한 코드이다.

object SharedPrefManager {

    private const val SHARED_SEARCH_HISTORY = "shared_search_history"
    private const val KEY_SEARCH_HISTORY = "key_search_history"

    // 검색 목록 저장
    fun storeSearchHistoryList(searchHistoryList: MutableList<SearchData>) {
        // 매개변수로 들어온 배열 -> 문자열 변환
        val searchHistoryListString: String = Gson().toJson(searchHistoryList)

        // 쉐어드 가져오기
        val shared = App.instance.getSharedPreferences(SHARED_SEARCH_HISTORY, Context.MODE_PRIVATE)

        // 쉐어드 에디터 가져오기
        // editor 초기화
        val editor = shared.edit()
        // editor 안에 원하는 value 넣기 - 어떤 자료형이든 사용 가능
        editor.putString(KEY_SEARCH_HISTORY, searchHistoryListString)
        // apply 또는 commit을 사용하여 editor에 넣은 값들을 저장
        editor.apply()
    }

    // 검색 목록 가져오기
    fun getSearchHistoryList(): MutableList<SearchData> {
        // 쉐어드 가져오기
        val shared = App.instance.getSharedPreferences(SHARED_SEARCH_HISTORY, Context.MODE_PRIVATE)

        //원하는 key 값의 value 를 가져옴
        val storedSearchHistoryListString = shared.getString(KEY_SEARCH_HISTORY, "")!!

        var storedSearchHistoryList = ArrayList<SearchData>()
        if (storedSearchHistoryListString.isNotEmpty()) {
            storedSearchHistoryList =
                Gson().fromJson(storedSearchHistoryListString, Array<SearchData>::class.java)
                    .toMutableList() as ArrayList<SearchData>
        }

        return storedSearchHistoryList
    }

}

그 외에 editor.remove("삭제하고 싶은 key")로 원하는 키값만 삭제하거나, editor.clear()로 전체 삭제를 할 수 있다. 변경한 후에는 꼭 editor.apply()로 반영해 주어야 한다.

profile
🐰 피드백은 언제나 환영합니다

0개의 댓글