MPAndroidChart中Activity间传递BarEntry报错:无法打包非可打包数据
解决Android传递BarEntry时的ParcelFormatException问题
这个错误android.os.ParcelFormatException: Cannot parcel an Entry with non-parcelable data的核心原因是:你使用的MPAndroidChart的BarEntry类虽然本身实现了Parcelable,但它携带的自定义data(也就是你传入的"Jan"、"Feb"这类字符串)在Parcel序列化过程中不被系统认可——MPAndroidChart的Entry基类在处理data字段时,要求它必须是Parcelable类型,否则就会抛出这个异常。而你用putSerializable传递集合时,底层依然会尝试用Parcel机制处理BarEntry对象,从而触发错误。
下面给你几个可行的解决方案:
方案一:拆分数据传递,在目标Activity重新绑定标签
这是最简单的方案,不需要修改BarEntry类:
- 在发送方(ChartRevenueActivity),把月份标签单独提取为一个数组,和BarEntry集合一起传递:
ArrayList<BarEntry> barEntries = new ArrayList<>(); // 初始化barEntries的代码不变... // 提取月份列表 ArrayList<String> monthLabels = new ArrayList<>(); monthLabels.add("Jan"); monthLabels.add("Feb"); monthLabels.add("Mar"); // ... 补充剩余月份 Intent barIntent = new Intent(ChartRevenueActivity.this, FullscreenActivity.class); // 用putParcelableArrayListExtra传递BarEntry(因为BarEntry本身是Parcelable) barIntent.putParcelableArrayListExtra("barEntries", barEntries); barIntent.putStringArrayListExtra("monthLabels", monthLabels); barIntent.putExtra("type", "barChart"); startActivity(barIntent);
- 在接收方(FullscreenActivity),重新给每个BarEntry绑定标签:
// 接收数据 ArrayList<BarEntry> barEntries = getIntent().getParcelableArrayListExtra("barEntries"); ArrayList<String> monthLabels = getIntent().getStringArrayListExtra("monthLabels"); // 重新绑定data字段 if (barEntries != null && monthLabels != null && barEntries.size() == monthLabels.size()) { for (int i = 0; i < barEntries.size(); i++) { barEntries.get(i).setData(monthLabels.get(i)); } } // 后续设置BarChart的代码不变...
方案二:自定义Parcelable的BarEntry子类
如果需要直接传递带data的BarEntry,可以自定义子类手动处理data的Parcel逻辑:
public class CustomBarEntry extends BarEntry implements Parcelable { public CustomBarEntry(float x, float[] y, Object data) { super(x, y, data); } // 从Parcel构造对象 protected CustomBarEntry(Parcel in) { super(in); // 这里假设data是String,直接读取字符串 setData(in.readString()); } // Parcelable Creator public static final Creator<CustomBarEntry> CREATOR = new Creator<CustomBarEntry>() { @Override public CustomBarEntry createFromParcel(Parcel in) { return new CustomBarEntry(in); } @Override public CustomBarEntry[] newArray(int size) { return new CustomBarEntry[size]; } }; @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); // 写入data(这里强制转为String,根据你的实际类型调整) dest.writeString((String) getData()); } }
然后在发送方使用这个自定义类:
ArrayList<CustomBarEntry> barEntries = new ArrayList<>(); barEntries.add(new CustomBarEntry(0, new float[]{8f, 9f, 10f}, "Jan")); // ... 其他条目初始化 Intent barIntent = new Intent(ChartRevenueActivity.this, FullscreenActivity.class); barIntent.putParcelableArrayListExtra("barEntries", barEntries); barIntent.putExtra("type", "barChart"); startActivity(barIntent);
接收方直接接收:
ArrayList<CustomBarEntry> barEntries = getIntent().getParcelableArrayListExtra("barEntries");
方案三:移除不必要的data字段
如果你的图表不需要显示这些月份标签,或者可以通过其他方式(比如XAxis的ValueFormatter)设置标签,那直接去掉BarEntry构造的第三个参数即可,这样默认的BarEntry就能正常传递:
barEntries.add(new BarEntry(0, new float[]{8f, 9f, 10f})); // 去掉第三个参数
内容的提问来源于stack exchange,提问作者Lim YC
相关产品推荐
相关产品推荐

