Having a Parcelable which has a lot members, and it has a private constructor so it can only be instantiated through a Builder. (And this class is also used in Java side of the code.)
Now would like to use @Parcelize
to remove some of the helper functions (like writeMapToParcel
etc.) to make the class simpler.
@Parcelize requires all serialized properties to be declared in the primary constructor (that will be a long list for us).
Question, can it still use Builder patten and with a private primary constructor? Or other suggested best practice?
class MessageData : Parcelable {
@JvmField var from: String = ""
@JvmField var sentTime: Long = 0
@JvmField var data: HashMap<String, String>
// it has long list of members not listed here...
private constructor(builder: Builder) {
from = builder.from
sentTime = builder.sentTime
data = builder.data
......
}
override fun describeContents(): Int {
return hashCode()
}
class Builder {
internal var from = ""
internal var sentTime: Long = 0
internal var data = HashMap<String, String>()
......
fun setFrom(from: String?): Builder {
this.from = from ?: ""
return this
}
fun setSentTime(sentTime: Long): Builder {
this.sentTime = sentTime
return this
}
fun setData(data: HashMap<String, String>?): Builder {
this.data = data ?: HashMap()
return this
}
fun build(): MessageData {
return MessageData(this)
}
}
// Parcelable
override fun writeToParcel(dest: Parcel, flags: Int) {
dest.writeString(from)
dest.writeLong(sentTime)
writeMapToParcel(dest, data)
......
}
protected constructor(p: Parcel) {
from = p.readString() ?: ""
sentTime = p.readLong()
data = getMapFromParcel(p)
......
}
fun getMapFromParcel(p: Parcel): HashMap<String, String> {
val hashMap = HashMap<String, String>()
val mapSize = p.readInt()
for (i in 0 until mapSize) {
val key = p.readString() ?: continue
val value = p.readString() ?: ""
hashMap[key] = value
}
return hashMap
}
fun writeMapToParcel(dest: Parcel, map: Map<String, String>) {
val mapSize = map.size
dest.writeInt(mapSize)
for ((key, value) in map) {
dest.writeString(key)
dest.writeString(value)
}
}
companion object {
@JvmField
val CREATOR: Parcelable.Creator<MessageData> = object : Parcelable.Creator<MessageData> {
override fun createFromParcel(source: Parcel): MessageData? {
return MessageData(source)
}
override fun newArray(size: Int): Array<MessageData?> {
return arrayOfNulls(size)
}
}
}
}