Reputation: 3429
I am trying to write a parcelable data object to pass to from activityA to activityB in my android application.
My object is passing with all the data, except my arraylist
of the class Available Service
data class AvailableService(val id: Int,
val name: String,
val description: String,
val price: Double,
val currency: String,
val imageUrl: String) : Parcelable {
companion object {
@JvmField @Suppress("unused")
val CREATOR = createParcel { AvailableService(it) }
}
protected constructor(parcelIn: Parcel) : this(parcelIn.readInt(),
parcelIn.readString(),
parcelIn.readString(),
parcelIn.readDouble(),
parcelIn.readString(),
parcelIn.readString())
override fun writeToParcel(dest: Parcel?, flags: Int) {
dest?.writeInt(id)
dest?.writeString(name)
dest?.writeString(description)
dest?.writeDouble(price)
dest?.writeString(currency)
dest?.writeString(imageUrl)
}
override fun describeContents() = 0
}
above is the available serviceClass
, next I have Trip, which holds an arraylist
of AvailableService
.. I observed this in debug, it is successfully writing the arraylist
, for some reason I have an issue with reading the data.
data class Trip(val id: String,
val status: String,
val orderedServices: ArrayList<OrderedService>) : Parcelable {
companion object {
@JvmField @Suppress("unused")
val CREATOR = createParcel { Trip(it) }
}
protected constructor(parcelIn: Parcel) : this(parcelIn.readString(),
parcelIn.readString(),
arrayListOf<OrderedService>().apply {
parcelIn.readArrayList(OrderedService::class.java.classLoader)
}
)
override fun writeToParcel(dest: Parcel?, flags: Int) {
dest?.writeString(id)
dest?.writeString(status)
dest?.writeList(orderedServices)
}
override fun describeContents() = 0
}
in case someone wonders what's the fun of the CREATOR does, code below:
inline fun <reified T : Parcelable> createParcel(
crossinline createFromParcel: (Parcel) -> T?): Parcelable.Creator<T> =
object : Parcelable.Creator<T> {
override fun createFromParcel(source: Parcel): T? = createFromParcel(source)
override fun newArray(size: Int): Array<out T?> = arrayOfNulls(size)
}
again, writing succeeds, but reading fails, I get an empty arraylist
..
I think that part is the faulty one:
arrayListOf<OrderedService>().apply {
parcelIn.readArrayList(OrderedService::class.java.classLoader)
}
is there a different way to read/write arraylist
? am I writing it wrong? reading it wrong?
thanks in advance for any help!
Upvotes: 26
Views: 31668
Reputation: 2657
If Parent and Child model have parcelable then used below one
Parent Model
Parcelable {
constructor(parcel: Parcel) : this(
parcel.createTypedArrayList(ImagesModel.CREATOR)
)
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeTypedList(images)
}
Upvotes: 3
Reputation: 1058
For API 29 and above
Replace:
arrayListOf<OrderedService>().apply {
parcelIn.readArrayList(OrderedService::class.java.classLoader)
}
with
if (Build.VERSION.SDK_INT >= 29)
parcel.readParcelableList(this, OrderedService::class.java.classLoader)
else
parcel.readList(this as List<OrderedService>, OrderedService::class.java.classLoader)
}
and
override fun writeToParcel(dest: Parcel?, flags: Int) {
dest?.writeString(id)
dest?.writeString(status)
dest?.writeList(orderedServices)
}
with
override fun writeToParcel(dest: Parcel?, flags: Int) {
dest?.writeString(id)
dest?.writeString(status)
if (Build.VERSION.SDK_INT >= 29) {
dest?.writeParcelableList(orderedServices,flags)
} else {
dest?.writeList(orderedServices as List<OrderedService>)
}
}
Upvotes: 6
Reputation: 1339
Change
arrayListOf<OrderedService>().apply {
parcelIn.readArrayList(OrderedService::class.java.classLoader)
}
to
source.createTypedArrayList(OrderedService.CREATOR)
Change dest?.writeList(orderedServices)
to dest?.writeTypedList(orderedServices)
The creator method
companion object {
@JvmField
val CREATOR: Parcelable.Creator<Trip> = object : Parcelable.Creator<Trip> {
override fun createFromParcel(source: Parcel): Trip = Trip(source)
override fun newArray(size: Int): Array<Trip?> = arrayOfNulls(size)
}
}
Upvotes: 7
Reputation: 456
Replace:
arrayListOf<OrderedService>().apply {
parcelIn.readArrayList(OrderedService::class.java.classLoader)
}
with:
arrayListOf<OrderedService>().apply {
parcelIn.readList(this, OrderedService::class.java.classLoader)
}
Upvotes: 42