2

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")
Pedro Coelho
  • 1,411
  • 3
  • 18
  • 31
lannyf
  • 9,865
  • 12
  • 70
  • 152

2 Answers2

3

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.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • thx! but if change to ArrayList> (need keep the order), crash: Parcelable IOException writing serializable object (name = kotlin.Pair) at com.test.IntRangeStringMap.writeToParcel(TestIntRangStringMap.kt) --- --- --- @Parcelize @TypeParceler() class IntRangeStringMap(val value: HashMap) : Parcelable == === === val rangeToSpaceMap: ArrayList>? = arrayListOf(Pair(IntRange(1, 5), “X”),Pair(IntRange(6, -1), “y”) === argument.putParcelable(“parelable_map”,IntRangeStringMap(rangeToSpaceMap!!)) – lannyf Feb 25 '20 at 14:46
  • You can use `LinkedHashMap` to keep the order. – Alexey Romanov Feb 25 '20 at 16:13
0

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
lannyf
  • 9,865
  • 12
  • 70
  • 152