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

从Adapter向非创建源Activity传递嵌套对象ArrayList为空的问题

问题分析与修复方案

看起来你在通过Adapter向非来源Activity传递嵌套Parcelable对象的ArrayList时踩了几个Parcelable实现的坑,导致对象列表始终为null。我帮你梳理下核心问题并给出修复方案:

1. Rate类的致命笔误

这是导致列表为null的最关键原因:

  • 构造函数名称错误:你把Rate类的构造函数写成了protected RateCard(Parcel in),但类名是Rate!这会导致CREATOR里的new Rate(in)调用失败,根本无法正确创建Rate实例
  • 成员变量名不匹配:类里定义的是private List<Rule> rateRules,但构造函数里写成了in.readList(this.rateCardRules, ...),数据根本没写到正确的变量上
  • List未初始化:如果原List是null,in.readList没办法把数据写入null对象,必须先初始化集合

修正后的Rate类代码:

public class Rate implements Parcelable{
    public final static Parcelable.Creator<Rate> CREATOR = new Creator<Rate>() {
        @SuppressWarnings({ "unchecked" })
        public Rate createFromParcel(Parcel in) {
            return new Rate(in);
        }
        public Rate[] newArray(int size) {
            return (new Rate[size]);
        }
    };

    @SerializedName("header")
    @Expose
    private String header;
    @SerializedName("body")
    @Expose
    private List<Body> body = null;
    @SerializedName("footer")
    @Expose
    private String footer;
    @SerializedName("type")
    @Expose
    private String rateCardType;
    @SerializedName("rules")
    @Expose
    private List<Rule> rateRules = null;

    // 修正构造函数名称,和类名保持一致
    protected Rate(Parcel in) {
        this.header = ((String) in.readValue((String.class.getClassLoader())));
        // 先初始化List再读取,避免null无法写入数据
        this.body = new ArrayList<>();
        in.readList(this.body, (Body.class.getClassLoader()));
        this.footer = ((String) in.readValue((String.class.getClassLoader())));
        this.rateCardType = ((String) in.readValue((String.class.getClassLoader())));
        // 修正变量名,同时初始化List
        this.rateRules = new ArrayList<>();
        in.readList(this.rateRules, (Rule.class.getClassLoader()));
    }

    public Rate() { }

    // 保留你原有的getter/setter方法
    public List<Rule> getRateCardRules() { return rateRules; }
    public void setRateCardRules(List<Rule> rateRules) { this.rateRules = rateRules; }
    public String getHeader() { return header; }
    public void setHeader(String header) { this.header = header; }
    public List<Body> getBody() { return body; }
    public void setBody(List<Body> body) { this.body = body; }
    public String getFooter() { return footer; }
    public void setFooter(String footer) { this.footer = footer; }
    public String getRateCardType() { return rateCardType; }
    public void setRateCardType(String rateCardType) { this.rateCardType = rateCardType; }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeValue(header);
        dest.writeList(body);
        dest.writeValue(footer);
        dest.writeValue(rateCardType);
        dest.writeList(rateRules);
    }

    @Override
    public int describeContents() {
        return 0;
    }
}

2. Rule类的潜在问题

Rule类的读写顺序看起来是对的,但同样存在List未初始化的问题,修复后更稳妥:

修正后的Rule类代码:

public class Rule implements Parcelable{
    public final static Parcelable.Creator<Rule> CREATOR = new Creator<Rule>() {
        @SuppressWarnings({ "unchecked" })
        public Rule createFromParcel(Parcel in) {
            return new Rule(in);
        }
        public Rule[] newArray(int size) {
            return (new Rule[size]);
        }
    };

    @SerializedName("rule")
    @Expose
    private DataRows ruleData;
    @SerializedName("rule_conditions")
    @Expose
    private List<DataRows> ruleConditions;
    @SerializedName("slots")
    @Expose
    private List<DataRows> slots;
    @SerializedName("header")
    @Expose
    private DataRows header;

    protected Rule(Parcel in) {
        // 初始化List再读取数据
        this.ruleConditions = new ArrayList<>();
        in.readList(this.ruleConditions, (DataRows.class.getClassLoader()));
        this.slots = new ArrayList<>();
        in.readList(this.slots, (DataRows.class.getClassLoader()));
        this.ruleData = in.readParcelable((DataRows.class.getClassLoader()));
        this.header = in.readParcelable((DataRows.class.getClassLoader()));
    }

    public Rule() { }

    // 保留你原有的getter/setter方法
    public DataRows getRuleData() { return ruleData; }
    public void setRuleData(DataRows ruleData) { this.ruleData = ruleData; }
    public List<DataRows> getRuleConditions() { return ruleConditions; }
    public void setRuleConditions(List<DataRows> ruleConditions) { this.ruleConditions = ruleConditions; }
    public List<DataRows> getSlots() { return slots; }
    public void setSlots(List<DataRows> slots) { this.slots = slots; }
    public DataRows getHeader() { return header; }
    public void setHeader(DataRows header) { this.header = header; }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeList(ruleConditions);
        dest.writeList(slots);
        dest.writeParcelable(ruleData, flags);
        dest.writeParcelable(header, flags);
    }

    @Override
    public int describeContents() {
        return 0;
    }
}

3. DataRows类(无需修改)

你的DataRows类实现是正确的,不需要调整。

最后,确保传递和接收数据的方式正确

在Adapter中传递数据时,用putParcelableArrayListExtra:

Intent intent = new Intent(context, YourTargetActivity.class);
// 注意要传入ArrayList类型,不能直接传List
intent.putParcelableArrayListExtra("KEY_RATE_LIST", new ArrayList<>(yourRateList));
context.startActivity(intent);

在目标Activity中接收:

ArrayList<Rate> rateList = getIntent().getParcelableArrayListExtra("KEY_RATE_LIST");

核心总结

  • 构造函数名称必须和类名完全一致,这是Parcelable实例化的基础
  • 读写Parcel的顺序必须严格对应,写的顺序和读的顺序不能乱
  • List类型的成员变量,读取前一定要先初始化(new一个ArrayList),否则null对象无法接收数据
  • 变量名要仔细核对,避免笔误导致数据写到错误的变量上

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:31:55