传递包含Activity之间Map的可传递对象

5

我的类 ExpenseFB 实现了 Parcelable,其中包含一个 UserFBMap(也实现了 Parcelable):

ExpenseFB

public class ExpenseFB implements Parcelable {

private String id;
private String name;
private String description;
private String whopaidID;
private String whopaidName;
private Double amount;
private Map<String, UserFB> partecipants;
// setters and getters...
@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(id);
    dest.writeString(name);
    dest.writeString(description);
    dest.writeString(whopaidID);
    dest.writeString(whopaidName);
    dest.writeMap(partecipants);
}


protected ExpenseFB(Parcel in) {
    id = in.readString();
    name = in.readString();
    description = in.readString();
    whopaidID = in.readString();
    whopaidName = in.readString();
    in.readMap(partecipants,UserFB.class.getClassLoader());
}

public static final Creator<ExpenseFB> CREATOR = new Creator<ExpenseFB>() {
    @Override
    public ExpenseFB createFromParcel(Parcel in) {
        return new ExpenseFB(in);
    }

    @Override
    public ExpenseFB[] newArray(int size) {
        return new ExpenseFB[size];
    }
};
}

UserFB:

public class UserFB implements Parcelable{

private String id;
private String name;
private String email;
private Map<String, GroupFB> groups;
private Map<String, UserFB> friends;
// setters and getters
@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(id);
    dest.writeString(name);
    dest.writeString(email);
    dest.writeMap(groups);
    dest.writeMap(friends);
}

protected UserFB(Parcel in) {
    id = in.readString();
    name = in.readString();
    email = in.readString();
    in.readMap(groups,GroupFB.class.getClassLoader());
    in.readMap(friends,UserFB.class.getClassLoader());
}

public static final Creator<UserFB> CREATOR = new Creator<UserFB>() {
    @Override
    public UserFB createFromParcel(Parcel in) {
        return new UserFB(in);
    }

    @Override
    public UserFB[] newArray(int size) {
        return new UserFB[size];
    }
};
}

我希望通过将ExpenseFB对象添加到Intent中,在两个活动之间传递它。
intent.putExtra("id", expenseFB);

当我在调试模式下执行getIntent().getParcelableExtra("id")时,在第二个活动中,当尝试对partecipants映射执行readMap()方法时,会引发以下异常:

 ... Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object java.util.Map.put(java.lang.Object, java.lang.Object)' on a null object reference

我发现第一个活动中的partecipants映射已经被填充了:我认为问题在于writeMap()方法中。
是否存在一种标准或更好的方法来传递包含映射的Parcelable对象?
我需要调用另一个方法来打包映射吗?

我不想使用Serializable对象,因为我读到它们会使性能变差。

2个回答

9
问题是readMap()被用来从Parcel中读取数据到一个已存在的Map中。在调用readMap()之前,你没有创建Map,所以会出现NullPointerException
你可以通过在声明时初始化map来解决这个问题:
private Map<String, GroupFB> groups = new HashMap<String, GroupFB>();
private Map<String, UserFB> friends = new HashMap<String, UserFB>();

或者,您可以在UserFB构造函数中创建空的Map,如下所示:
protected UserFB(Parcel in) {
    id = in.readString();
    name = in.readString();
    email = in.readString();
    groups = new HashMap<String, GroupFB>();
    in.readMap(groups,GroupFB.class.getClassLoader());
    friends = new HashMap<String, UserFB>()
    in.readMap(friends,UserFB.class.getClassLoader());
}

1
你已经有了思路,但我认为你需要知道如何将 Map<> 写入 parcelablewriteParcel() 方法粘贴进去
@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeInt(this.groups.size());
    for (Map.Entry<String, GroupFb> entry : this.groups.entrySet()) {
        dest.writeString(entry.getKey());
        dest.writeParcelable(entry.getValue(), flags);
    }
}

protected UserFB (Parcel in) {
    int groupsSize = in.readInt();
    this.groups = new HashMap<String, GroupFb>(groupsSize);
    for (int i = 0; i < groupsSize; i++) {
        String key = in.readString();
        GroupFb value = in.readParcelable(GroupFb.class.getClassLoader());
        this.groups.put(key, value);
    }
}

也对另一个 Map<> 做同样的操作。


1
Parcel类已经有了writeMap()readMap()方法,可以完美地实现这个功能。为什么不使用现有的方法呢?在这里没有必要重新发明轮子。 - David Wasser
2
不建议使用writeMap()方法,因为它在javadoc中已经被说明。此外,它只适用于map中的字符串键情况。因此,这个答案更加通用和正确。 - Taras Lozovyi

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