My class ExpenseFB
, which implements Parcelable
, contains a Map
of UserFB
(which implements Parcelable
too):
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];
}
};
}
I want to pass an ExpenseFB object between two Activities by adding the object
ExpenseFB
to the intent:
intent.putExtra("id", expenseFB);
When, in debug mode, I execute getIntent().getParcelableExtra("id")
in the second activity it raises the following exception when tries to do the readMap()
method on the partecipants
map:
... 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
I see that the partecipants
map in the first activity is filled: I think that the problem is in the writeMap() method.
Does exist a standard or better way to pass a Parcelable
object containing a Map?
Have I to call another method to parcel the Map?
I don't want to use Serializable
object because I read that they make worse performances.
Suppose you have a class Foo implements Parcelable properly, to put it into Intent in an Activity: Intent intent = new Intent(getBaseContext(), NextActivity. class); Foo foo = new Foo(); intent. putExtra("foo ", foo); startActivity(intent);
Create Parcelable class without plugin in Android Studioimplements Parcelable in your class and then put cursor on "implements Parcelable" and hit Alt+Enter and select Add Parcelable implementation (see image). that's it.
Parcelable is a serialization mechanism provided by Android to pass complex data from one activity to another activity.In order to write an object to a Parcel, that object should implement the interface “Parcelable“.
You should only implement parcelable for data objects and never for Views, the idea is to parcel/unparcel the data state to re-instantiate a given View with state. Also, implementing parcelable by hand is pretty tedious and could be error prone.
The problem is that readMap()
is used to read data from a Parcel
into and existing Map
. You haven't created the Map
before calling readMap()
, so you get the NullPointerException
.
You can solve this by initializing the map when you declare it:
private Map<String, GroupFB> groups = new HashMap<String, GroupFB>();
private Map<String, UserFB> friends = new HashMap<String, UserFB>();
Or, you can create the empty Map
in the UserFB
constructor, like this:
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());
}
You got the point but I think you need to know how to write Map<>
into parcelable
Pasting writeParcel()
method
@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);
}
}
Do the same for another Map<>
too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With