Kotlin:如何将HashMap放入Parcelable中

3

在一个实现了Parcelable接口的类中,有一个HashMap成员。

看到Parcelable有public final void readMap(Map outVal, ClassLoader loader)方法,但找不到使用它的示例。

如果通过扁平化映射并相应地逐个写/读,如何在构造函数中从包裹中提取?(从可包裹对象构建映射时出错,cannot access buildTheMap() before constructor is called

class CachedData(val type: Int,
             val name: String,
             val details: HashMap<String, String) :
    Parcelable {

constructor(parcel: Parcel) : this(
        parcel.readInt(),
        parcel.readString(),

        // how to get the hashMap out of the parcel???
        buildTheMap(parcel)   //<=== cannot access buildTheMap() before constructor is called
)

fun buildTheMap(parcel: Parcel) :HashMap<String, String> {

    val size = parcel.readInt()
    val map = HashMap<String, String>()

    for (i in 1..size) {
        val key = parcel.readString()
        val value = parcel.readString()
        map[key] = value
    }
    return map
}

override fun writeToParcel(parcel: Parcel, flags: Int) {
    parcel.writeInt(type)
    parcel.writeString(name)

    // how to write the HashMap<String, String> to the parcel
    //parcel.???

    parcel.writeInt(details.size)
    for ((key, value) in details) {
        parcel.writeString(key)
        parcel.writeString(value)
    }
}

override fun describeContents(): Int {
    return 0
}

companion object {
    @JvmField val CREATOR: Parcelable.Creator<CachedData> = object : Parcelable.Creator<CachedData>{
        override fun createFromParcel(parcel: Parcel): CachedData {
            return CachedData(parcel)
        }

        override fun newArray(size: Int): Array<CachedData?> {
            return arrayOfNulls(size)
        }
    }
}

}

3个回答

6

对于我遇到的同样问题,我的解决方案是:

public class JoustBattler extends Parcelable {

...

 private Map<String, Integer> battleWins;


 protected JoustBattler(Parcel in) {
        super(in);

        int battleWinsSize = in.readInt();
        this.battleWins = new HashMap<String, Integer>(battleWinsSize);
        for (int i = 0; i < battleWinsSize; i++) {
            String key = in.readString();
            Integer value = (Integer) in.readValue(Integer.class.getClassLoader());
            this.battleWins.put(key, value);
        }

    }


    @Override
    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);

        dest.writeInt(this.battleWins.size());
        for (Map.Entry<String, Integer> entry : this.battleWins.entrySet()) {
            dest.writeString(entry.getKey());
            dest.writeValue(entry.getValue());
        }

    }

希望这有所帮助,祝你好运!

感谢@Serg!因为建议不使用主构造函数语法,所以加1。它有效。希望有其他使用内置final void readMap(Map outVal, ClassLoader loader)的示例。 - lannyf

5

我希望您能分享如何使用readMap()函数。

以下是用Kotlin编写的将map扁平化的代码,供参考。

class CachedData :
    Parcelable {

var type: Int = 0
var name: String = ""
var details: HashMap<String, String> = HashMap()

constructor (type: Int,
             name: String,
             details: HashMap<String, String>) {
    this.type = type
    this.name = name
    this.details = details
}

constructor(parcel: Parcel) {
    this.type = parcel.readInt()
    this.name = parcel.readString()
    this.details = buildTheMap(parcel)
}

fun buildTheMap(parcel: Parcel): HashMap<String, String> {

    val size = parcel.readInt()
    val map = HashMap<String, String>(size)

    for (i in 1..size) {
        val key = parcel.readString()
        val value = parcel.readString()
        map[key] = value
    }
    return map
}

fun writeToMap(parcel: Parcel) {
    parcel.writeInt(details.size)
    for ((key, value) in details) {
        parcel.writeString(key)
        parcel.writeString(value)
    }
}

override fun writeToParcel(parcel: Parcel, flags: Int) {
    parcel.writeInt(type)
    parcel.writeString(name)
    writeToMap(parcel)
}

override fun describeContents(): Int {
    return 0
}

companion object {
    @JvmField
    val CREATOR: Parcelable.Creator<CachedData> = object : Parcelable.Creator<CachedData> {
        override fun createFromParcel(parcel: Parcel): CachedData {
            return CachedData(parcel)
        }

        override fun newArray(size: Int): Array<CachedData?> {
            return arrayOfNulls(size)
        }
    }
}
} 

3
使用@Parcelize,只需编写代码即可。
@Parcelize
class CachedData(val type: Int, val name: String, val details: HashMap<String, String>) : Parcelable

它内置支持HashMap(以及其他集合类型)。


太棒了!请注意,您需要将 plugins {id 'kotlin-parcelize'} 添加到您的模块 build.gradle 中才能使其正常工作。 - Dan Chaltiel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接