lannyf
lannyf

Reputation: 11025

kotlin, how to make a hashMap parcelable

Having a variable is hashMap<IntRange, String>, and need to put in bundle as parcelable to be saved and restored in onSaveStateInstance()/onCreateView() :

val map: HashMap<IntRange, String>? = hashMapOf(IntRange(0, 4) to "x", IntRange(5, -1) to "y")

and do

//saving:
outState.putParcelable("saved_map", map)

...
//retrieving: 
val map = bundle.getParcelable("saved_map")

Upvotes: 2

Views: 1688

Answers (2)

lannyf
lannyf

Reputation: 11025

based on @Alexey Romanov's answer, got a working version

I changed to making a parcelable ArrayList<Pair<IntRange, String>>

object IntRangeParceler : Parceler<IntRange> {
    override fun create(parcel: Parcel) = IntRange(parcel.readInt(), parcel.readInt())

    override fun IntRange.write(parcel: Parcel, flags: Int) {
        parcel.writeInt(first)
        parcel.writeInt(last)
    }
}

object PairParceler : Parceler<Pair<IntRange, String>> {
    override fun create(parcel: Parcel): Pair<IntRange, String> =
        Pair(IntRange(parcel.readInt(), parcel.readInt()), parcel.readString())

    override fun Pair<IntRange, String>.write(parcel: Parcel, flags: Int) {
        parcel.writeInt(first.first)
        parcel.writeInt(first.last)
        parcel.writeString(second)
    }
}

@Parcelize
@TypeParceler<IntRange, IntRangeParceler>()
@TypeParceler<Pair<IntRange, String>, PairParceler>()
class IntRangeStringMap(val value:  ArrayList<Pair<IntRange, String>>) : Parcelable

Upvotes: 0

Alexey Romanov
Alexey Romanov

Reputation: 170735

I would suggest using a wrapper class nonetheless, just because it's much simpler in Kotlin than in Java. @Parcelize supports HashMap, the problem is that it doesn't support IntRange (or at least it isn't listed). But based on the example there, it seems this should work:

object IntRangeParceler : Parceler<IntRange> {
    override fun create(parcel: Parcel) = IntRange(parcel.readInt(), parcel.readInt())

    override fun IntRange.write(parcel: Parcel, flags: Int) {
        parcel.writeInt(value, start)
        parcel.writeInt(value, endInclusive)
    }
}

@Parcelize
@TypeParceler<IntRange, IntRangeParceler>()
class IntRangeStringMap(val value: HashMap<IntRange, String>)

and your calls become

outState.putParcelable("saved_map", IntRangeStringMap(map))
val map = bundle.getParcelable("saved_map").value

You can even get it looking the way you want by adding extension functions.

Upvotes: 3

Related Questions