You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中使用Parcelable读取List<List<List<Double>>>及类转换异常处理

问题解决方案

根因分析

  • GET请求正常是因为Gson直接从服务端返回的JSON反序列化生成Polygon对象,coordinates的三层List<Double>结构完全正确
  • 报错出现在POST序列化阶段,核心原因是Polygon类的Parcelable实现有问题:默认的writeList()/readList()方法无法保留嵌套集合的泛型类型信息,经过Parcel序列化(比如跨页面传递对象)后,coordinates内部的结构被破坏,原本的嵌套集合位置出现了Double类型的元素,Gson序列化时遍历集合期望拿到Collection类型,实际拿到Double就抛出了类型转换异常。

修复方案(不影响原有GET请求逻辑)

方案1:修改Parcelable的序列化/反序列化逻辑,手动处理三层嵌套集合

修改你的Polygon类中的writeToParcel方法和Parcel构造方法,代码如下:

// 修改writeToParcel方法
@Override
public void writeToParcel(android.os.Parcel dest, int flags) {
    dest.writeValue(type);
    // 手动写入三层List结构
    if (coordinates == null) {
        dest.writeInt(-1);
        return;
    }
    // 写入第一层size
    dest.writeInt(coordinates.size());
    for (List<List<Double>> secondLevel : coordinates) {
        if (secondLevel == null) {
            dest.writeInt(-1);
            continue;
        }
        // 写入第二层size
        dest.writeInt(secondLevel.size());
        for (List<Double> thirdLevel : secondLevel) {
            if (thirdLevel == null) {
                dest.writeInt(-1);
                continue;
            }
            // 写入第三层size
            dest.writeInt(thirdLevel.size());
            for (Double d : thirdLevel) {
                dest.writeDouble(d);
            }
        }
    }
}

// 修改Parcel构造方法
protected Polygon(android.os.Parcel in) {
    this.type = ((String) in.readValue((String.class.getClassLoader())));
    // 手动读取三层List结构
    int firstSize = in.readInt();
    if (firstSize == -1) {
        coordinates = null;
        return;
    }
    coordinates = new ArrayList<>(firstSize);
    for (int i = 0; i < firstSize; i++) {
        int secondSize = in.readInt();
        if (secondSize == -1) {
            coordinates.add(null);
            continue;
        }
        List<List<Double>> secondLevel = new ArrayList<>(secondSize);
        coordinates.add(secondLevel);
        for (int j = 0; j < secondSize; j++) {
            int thirdSize = in.readInt();
            if (thirdSize == -1) {
                secondLevel.add(null);
                continue;
            }
            List<Double> thirdLevel = new ArrayList<>(thirdSize);
            secondLevel.add(thirdLevel);
            for (int k = 0; k < thirdSize; k++) {
                thirdLevel.add(in.readDouble());
            }
        }
    }
}

方案2:临时修复(适合不想修改模型类的场景)

如果你的Polygon对象经过了Parcel传递,在构造POST请求之前,手动深拷贝一份coordinates的三层集合,再赋值给要序列化的对象即可:

// 深拷贝coordinates
List<List<List<Double>>> newCoordinates = new ArrayList<>();
for (List<List<Double>> second : oldPolygon.getCoordinates()) {
    List<List<Double>> newSecond = new ArrayList<>();
    for (List<Double> third : second) {
        newSecond.add(new ArrayList<>(third));
    }
    newCoordinates.add(newSecond);
}
Polygon postPolygon = new Polygon();
postPolygon.setType(oldPolygon.getType());
postPolygon.setCoordinates(newCoordinates);
// 用postPolygon去做POST请求即可

验证说明

两种方案都不会修改原有Gson反序列化的逻辑,所以GET请求的响应解析完全不受影响,同时修复了Parcel序列化导致的集合结构异常问题,POST请求序列化时就不会再抛出类型转换异常。

内容的提问来源于stack exchange,提问作者Roon13

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 04:36:05