意图getextra中嵌套Parcelable的空指针异常
Posted
技术标签:
【中文标题】意图getextra中嵌套Parcelable的空指针异常【英文标题】:null pointer exception of nested Parcelable in intent getextra 【发布时间】:2020-09-03 03:14:36 【问题描述】:我有一个嵌套的 parcelable 类(内部有 Provider 类的 Product 类)。我想将 Product 对象发送到另一个具有额外意图的活动。当我有意图时,提供者对象为空。
Outer(Parent) 类是 Product(为方便起见,省略了 setter 和 getter):
public class Product implements Parcelable
public static final String KEY_CART_COUNT = "KEY_CART_COUNT";
private int id;
private String title;
private String description;
@SerializedName("category_id")
private int categoryId;
@SerializedName("city_id")
private int cityId;
private String fee;
private String fee2;
@SerializedName("main_cat")
private Integer mainCategory;
@SerializedName("barcode_type")
private String barcodeType;
@SerializedName("barcode_text")
private String barcodeText;
private String unit;
private String image;
@SerializedName("is_active")
private int isActive;
@SerializedName("now")
private long now;
//*****************************************************************
@SerializedName("provider_info")
private Provider provider;
//*****************************************************************
@SerializedName("is_bookmarked")
private boolean isBookmarked;
@SerializedName("image_url")
private String imageUrl;
@SerializedName("exists_number")
private int existsNumber;
@SerializedName("buy_limit")
private int buyLimit;
private long addToCartTime;
private int cartCount;
protected Product(Parcel in)
id = in.readInt();
title = in.readString();
description = in.readString();
categoryId = in.readInt();
cityId = in.readInt();
fee = in.readString();
fee2 = in.readString();
barcodeType = in.readString();
barcodeText = in.readString();
unit = in.readString();
image = in.readString();
isActive = in.readInt();
cartCount = in.readInt();
isBookmarked = in.readByte() != 0;
mainCategory = in.readInt();
imageUrl = in.readString();
existsNumber = in.readInt();
buyLimit = in.readInt();
addToCartTime = in.readLong();
provider = in.readParcelable(Provider.class.getClassLoader());
public Product()
this.addToCartTime = Calendar.getInstance().getTime().getTime();
public Product(Product newProduct)
this.id = newProduct.id;
this.title = newProduct.title;
this.description = newProduct.description;
this.categoryId = newProduct.categoryId;
this.cityId = newProduct.cityId;
this.fee = newProduct.fee;
this.fee2 = newProduct.fee2;
this.barcodeType = newProduct.barcodeType;
this.barcodeText = newProduct.barcodeText;
this.unit = newProduct.unit;
this.image = newProduct.image;
this.isActive = newProduct.isActive;
this.mainCategory = newProduct.mainCategory;
this.cartCount = newProduct.cartCount;
this.isBookmarked = newProduct.isBookmarked;
this.imageUrl = newProduct.imageUrl;
this.existsNumber = newProduct.existsNumber;
this.buyLimit = newProduct.buyLimit;
this.addToCartTime = newProduct.addToCartTime;
@Override
public void writeToParcel(Parcel dest, int flags)
dest.writeInt(id);
dest.writeString(title);
dest.writeString(description);
dest.writeInt(categoryId);
dest.writeInt(cityId);
dest.writeString(fee);
dest.writeString(fee2);
dest.writeString(barcodeType);
dest.writeString(barcodeText);
dest.writeString(unit);
dest.writeString(image);
dest.writeInt(isActive);
dest.writeInt(cartCount);
dest.writeInt(mainCategory);
dest.writeByte((byte) (isBookmarked ? 1 : 0));
dest.writeString(imageUrl);
dest.writeInt(existsNumber);
dest.writeInt(buyLimit);
dest.writeLong(addToCartTime);
dest.writeValue(provider);
@Override
public int describeContents()
return 0;
public static final Creator<Product> CREATOR = new Creator<Product>()
@Override
public Product createFromParcel(Parcel in)
return new Product(in);
@Override
public Product[] newArray(int size)
return new Product[size];
;
这是我的 Provider 类:
public class Provider implements Parcelable
public static final Creator<Provider> CREATOR = new Creator<Provider>()
@Override
public Provider createFromParcel(Parcel in)
return new Provider(in);
@Override
public Provider[] newArray(int size)
return new Provider[size];
;
private int id;
@SerializedName("title")
private String title;
@SerializedName("description")
private String description;
@SerializedName("admin_id")
private int admin_id;
@SerializedName("provider_id")
private int provider_id;
@SerializedName("start1")
private String start1;
@SerializedName("start2")
private String start2;
@SerializedName("end1")
private String end1;
@SerializedName("end2")
private String end2;
protected Provider(Parcel in)
id = in.readInt();
title = in.readString();
description = in.readString();
admin_id = in.readInt();
provider_id = in.readInt();
start1 = in.readString();
start2 = in.readString();
end1 = in.readString();
end2 = in.readString();
@Override
public int describeContents()
return 0;
@Override
public void writeToParcel(Parcel parcel, int i)
parcel.writeInt(id);
parcel.writeString(title);
parcel.writeString(description);
parcel.writeInt(admin_id);
parcel.writeInt(provider_id);
parcel.writeString(start1);
parcel.writeString(end1);
parcel.writeString(start2);
parcel.writeString(end2);
将产品数组发送到 ProductDetailActivity 的代码:
Intent starter = new Intent(context, ProductDetailActivity.class);
starter.putParcelableArrayListExtra(Constants.ACTIVITY_EXTRA_PRODUCTS, new ArrayList<>(products));
context.startActivity(starter);
最后在 ProductDetailActivity 中获取产品:
getIntent().getParcelableArrayListExtra(Constants.ACTIVITY_EXTRA_PRODUCTS)
【问题讨论】:
不确定是否足以解释此问题,但读/写 mainCategory 和 isBookmarked 的顺序混淆了。开始/结束字段也存在类似的排序问题。 你的意思是写和读字段的顺序应该是一样的吗? 当然可以。 Parcel 只是一个数据流。要取回相同的数据,您必须按顺序配对读取和写入。 【参考方案1】:正如laalto 建议的产品类(或任何 Parcelable 类)中的数据顺序在读写时应相同。我把我的代码改成了这个,它运行良好:
@Override
public void writeToParcel(Parcel dest, int flags)
dest.writeInt(id);
dest.writeString(title);
dest.writeString(description);
dest.writeInt(categoryId);
dest.writeInt(cityId);
dest.writeString(fee);
dest.writeString(fee2);
dest.writeString(barcodeType);
dest.writeString(barcodeText);
dest.writeString(unit);
dest.writeString(image);
dest.writeInt(isActive);
dest.writeInt(cartCount);
dest.writeByte((byte) (isBookmarked ? 1 : 0));// Changed Order
dest.writeInt(mainCategory); // Changed Order
dest.writeString(imageUrl);
dest.writeInt(existsNumber);
dest.writeInt(buyLimit);
dest.writeLong(addToCartTime);
dest.writeLong(now);
dest.writeParcelable(provider, flags); // **Changed from writeValue to writeParcelable**
【讨论】:
以上是关于意图getextra中嵌套Parcelable的空指针异常的主要内容,如果未能解决你的问题,请参考以下文章
当意图传递给其他活动时,为啥从 parcelable 中得到错误的值?
intent.getextra() 正在接收 null 并且 intent.hasextra() 在第二个活动中不起作用
如何将 putExtra() 和 getExtra() 用于字符串数据