[Android] Parcelable in Kotlin

2019. 3. 6. 09:38Programming/Android

반응형

[스마이트]일단 뼈대는 완성했다.를 만들면서 Activity간에 Data Class를 전달해야 할 일이 발생했다. 사실 아이템과 관련된 내용들을 전체 Activity에서 사용하기 때문에, 굳이 Data Class를 전달하지 않고도 사용할 방법을 찾으려면 찾을 수는 있었겠지만…

예전에는 Serializable을 사용했던 걸로 기억하지만, Serializable은 내부적으로 많은 리플렉션과 다량의 오브젝트를 생성하기 때문에, 안드로이드 앱의 전체적인 성능을 낮추며 배터리를 소모하는 원인이 된다고 한다. (Parcelable과 Serializable 비교, Charles 님) 물론 Kotlin이 Java Wrapper는 아니지만, Serializable을 사용하더라도 크게 다르지는 않을 듯 싶다. - (Kotlin, 어떻게 동작하나요, Chang W. Doh님)

Parcelable을 적용하기 위해서는 사용할 Data Class가 Parcelable을 상속받게끔 구현한 뒤, 생성자, writeToParcel, describeContents, CREATOR를 구현해주면 된다. Data Class를 Parcelable Object로 전달한 뒤, 원래의 Data Class로 변환하여 사용하기 때문인 듯 하다. 구현하고나면 Parcelable을 사용하여, Object를 전달할 수 있다. - (Parcelable을 사용한 오브젝트 전달(Object serialization using Parcelable), ArsViator 님)

개인적으로는 Data Class 안에 Data Class가 포함되어있을 경우, 어떻게 처리해야할지에 대한 자료를 찾지 못했다. Data Class가 총 세 개 있었는데, 서로 계층구조를 이루고 있었다. 따로따로 구현하자니 생각보다 손이 많이 갔다. 하지만 JSON File에 손을 댈 경우 스마이트 홈페이지에서 데이터를 받아서 업데이트 하기 귀찮아지므로, 좀 더 편한 방법을 생각해야 했다.

물론 Data Class를 JSON Object의 형식에 맞춰서 작성할 필요는 없었다. 어차피 JSON Object는 읽어서 데이터를 생성할 때의 문제지, Data Class를 내 마음대로 정의한다고 문제가 될 일은 없었기 때문이다. 단지 문제에 직면했을 때 1차원적으로 생각했기 때문에 발생한 문제다. Data Class의 구조를 변경했다면, 오히려 구조가 쉬워질 수도 있었을 것이다.

아무튼 다시 원점으로 돌아와서, Kotlin 1.1.4부터 추가된 Parcelize을 이용해서 이를 쉽게 해결할 수 있었다.

An automatic Parcelable implementation generator. Declare the serialized properties in a primary constructor and add a @Parcelize annotation, and writeToParcel()/createFromParcel() methods will be created automatically

@Parcelize annotation을 사용하면, writeToParcel()/createFromParcel()를 자동으로 구현해준다는 내용이다. 정말이지 편리하다. 이를 사용하기 위해서는 우선, build.gradle 파일에 다음의 코드를 추가해줘야 한다. experimental이라는 이름이 좀 신경쓰이긴 하지만, 아무튼 이 값을 true로 변경하면 된다.

androidExtensions {
  experimental = true
}

그 다음에는 Parecelable을 상속할 Data Class의 Primary constructor앞에 @Parcelize를 붙여주기만 하면 된다. Data Class를 안에 Data Class가 포함된 경우에는 하위 Data Class에도 동일하게 @Parcelize를 사용하면, 자동으로 구현이 된다. 다음은 이를 적용한 내용이다.

@Parcelize
data class MenuItem(
    val Description:String,
    val Description_kr:String,
    val Value:String
):Parcelable

@Parcelize
data class ItemDescription(
    val Description: String,
    val Description_kr: String,
    val menuItems: ArrayList<MenuItem>,
    val SecondaryDescription: String,
    val SecondaryDescription_kr: String
):Parcelable

@Parcelize
data class Item(
    val ChildItemId:Int,
    val DeviceName:String,
    val IconId:Int,
    val ItemDescription:ItemDescription,
    val ItemId: Int,
    val ItemTier: Int,
    val Price: Int,
    val RestrictedRoles: String,
    val RestrictedRoles_kr: String,
    val RootItemId: Int,
    val ShortDesc: String,
    val StartingItem: Boolean,
    val Type: String,
    val itemIcon_URL: String,
    val ret_msg: String? = null
):Parcelable

@Parcelize를 사용했을 때 발생할 수 있는 문제가 두 가지 있는데, 하나는 Kotlin 1.1.5부터는 회피가 가능하다고 하며, 다른 하나는 Android 4.4이하 버전의 사용자가 설치하지 못하는 상황이 발생할 수 있다는 내용이다. 지금 글을 작성하고 있는 시점(2019-03-06)에서는 이미 Android 4.4의 지원이 끊긴 상태이므로 크게 문제는 되지 않으리라 생각하지만, 업무에 적용할 시에는 유의할 필요가 있다. - (Parcelable in Kotlin? Here comes Parcelize, Joao Alves 님)

참조:
Parcelable, Android Developers
Easy Parcelable in Kotlin, Zahidur Rahman Faisal 님
Kotlin Parcelable 플러그인 사용하기, Taehwan 님
[Android] Parcelable에 대한 쉬운 이해, 명동콜링 님
Is there a convenient way to create Parcelabe data classes in Android with Kotlin?, StackOverflow


Parcelable과 Serializable 비교, Charles 님

반응형