Reputation: 400
I got this error when running this snippet of code from a fragment HomeFragment
public void onTaskClick(View view, Need need, int position) {
Log.d(TAG, "onTaskClick() - " + need.toString());
Intent intent = new Intent(getActivity(), TaskDetailsActivity.class);
Bundle bundle = new Bundle();
bundle.putParcelable(TaskDetailsActivity.EXTRA_OBJ_NEED, Parcels.wrap(need));
startActivity(intent, bundle);
}
Here is Need.java
@Parcel(implementations = {NeedRealmProxy.class}, value = Parcel.Serialization.FIELD, analyze = { Need.class })
public class Need extends RealmObject implements Serializable {
@PrimaryKey
@SerializedName("_id")
private String id;
@SerializedName("created")
private Date created;
@SerializedName("status")
private String status;
@SerializedName("fees")
float fees;
@SerializedName("user")
private User user;
@ParcelPropertyConverter(RealmListParcelConverter.class)
@SerializedName("places")
private RealmList<Place> places;
@SerializedName("user_location")
private Place userLocation;
@ParcelPropertyConverter(RealmListParcelConverter.class)
@SerializedName("items_ordered")
private RealmList<ItemOrdered> itemsOrdered;
@ParcelPropertyConverter(RealmListParcelConverter.class)
@SerializedName("movings")
private RealmList<Moving> movings;
@ParcelPropertyConverter(RealmListParcelConverter.class)
@SerializedName("messages")
private RealmList<Message> messages;
@SerializedName("run")
private Run run;
public Need() {}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public List<Place> getPlaces() {
return places;
}
public List<ItemOrdered> getItemsOrdered() {
return itemsOrdered;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Double getAmount() {
double p = 0;
for (ItemOrdered e: itemsOrdered) {
if (e.getItem().getPrice() != null) {
p += e.getItem().getPrice() * e.getQuantity();
}
}
return p;
}
public Place getUserLocation() {
return userLocation;
}
public void setUserLocation(Place userLocation) {
this.userLocation = userLocation;
}
public Date getCreated() {
return created;
}
public String getCreatedFormatted() {
SimpleDateFormat format = new SimpleDateFormat("MMM dd, HH:mm");
return format.format(created);
}
public void setCreated(Date created) {
this.created = created;
}
public String getStatus() {
return status;
}
public List<Message> getMessages() {
return messages;
}
public Run getRun() {
return this.run;
}
public List<Moving> getMovings() {
return movings;
}
public void setMovings(RealmList<Moving> movings) {
this.movings = movings;
}
public float getFees() {
return fees;
}
public void setFees(float fees) {
this.fees = fees;
}
public void setPlaces(RealmList<Place> places) {
this.places = places;
}
public void setItemsOrdered(RealmList<ItemOrdered> itemsOrdered) {
this.itemsOrdered = itemsOrdered;
}
public void setMessages(RealmList<Message> messages) {
this.messages = messages;
}
@Override
public String toString() {
return "Need{" +
"id= '" + id + '\'' +
", movings='" + movings.size() + '\'' +
", places=" + places.size() +
", itemsOrdered=" + itemsOrdered.size() +
", userLocation=" + userLocation.getLng() + "," + userLocation.getLat() +
", user=" + user +
'}';
}
}
Here is RealmListParcelConverter.java
public class RealmListParcelConverter implements
TypeRangeParcelConverter<RealmList<? extends RealmObject>, RealmList<? extends RealmObject>> {
private static final int NULL = -1;
@Override
public void toParcel(RealmList<? extends RealmObject> input, android.os.Parcel parcel) {
parcel.writeInt(input == null ? NULL : input.size());
if (input != null) {
for (RealmObject item : input) {
parcel.writeParcelable(Parcels.wrap(item), 0);
}
}
}
@Override
public RealmList fromParcel(android.os.Parcel parcel) {
int size = parcel.readInt();
RealmList list = new RealmList();
for (int i=0; i<size; i++) {
Parcelable parcelable = parcel.readParcelable(getClass().getClassLoader());
list.add((RealmObject) Parcels.unwrap(parcelable));
}
return list;
}
}
Error
android.os.BadParcelableException: ClassNotFoundException when unmarshalling: io.realm.NeedRealmProxy$$Parcelable at android.os.Parcel.readException(Parcel.java:1427) at android.os.Parcel.readException(Parcel.java:1379) at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:1761) at android.app.Instrumentation.execStartActivity(Instrumentation.java:1411) at android.app.Activity.startActivityForResult(Activity.java:3351) at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:50) at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:79) at android.support.v4.app.ActivityCompatJB.startActivityForResult(ActivityCompatJB.java:30) at android.support.v4.app.ActivityCompat.startActivityForResult(ActivityCompat.java:146) at android.support.v4.app.FragmentActivity.startActivityFromFragment(FragmentActivity.java:932) at android.support.v4.app.FragmentActivity$HostCallbacks.onStartActivityFromFragment(FragmentActivity.java:1047) at android.support.v4.app.Fragment.startActivity(Fragment.java:940) at com.nkapsi.ui.fragment.HomeFragment.onTaskClick(HomeFragment.java:201)
Upvotes: 2
Views: 545
Reputation: 786
RealmObject can't be Serializable. So you will not be able to pass any RealmObject using put extra. In that case you should pass the id of the RealmObject. And in the target Activity you should query for the RealmObject using this id. As @Eric Maxwell answered.
Upvotes: 0
Reputation: 76
You should pass the id instead and pull the object out by id on the other side.
Something like:
public void onTaskClick(View view, Need need, int position) {
Log.d(TAG, "onTaskClick() - " + need.toString());
Intent intent = new Intent(getActivity(), TaskDetailsActivity.class);
intent.putExtra("need_id", need.getId());
startActivity(intent);
}
Then in the Activity receiving the id, get the object back out.
// in onCreate(), onHandleIntent(), etc.
// get the needId back out.
String needId = intent.getStringExtra("need_id");
// get the object out by id.
realm.where(Need.class).equalTo("id", needId).findFirst();
// Lookup by PK is super fast, but if you want you can always use
realm.where(Need.class).equalTo("id", needId).findFirstAsync();
// This will make this microsecond lookup happen on a background thread
// and return the object back to you on your main thread, but is
// probably overkill for a single object.
More on this (https://realm.io/docs/java/latest/#intents)
Upvotes: 3
Reputation: 81529
Do
@Parcel(value = Parcel.Serialization.FIELD, analyze = { Need.class })
and
bundle.putParcelable(TaskDetailsActivity.EXTRA_OBJ_NEED, Parcels.wrap(realm.copyFromRealm(need)));
P.S. typically you just need to send the primary key of the object though, not the whole object.
But based on the realm-java issues, apparently you need following proguard config
-keepnames public class * extends io.realm.RealmObject
Upvotes: 0