I have two classes, let's assume they look like these:
Movie.java
public class Movie implements Parcelable {
private int year;
private List<Actor> actors;
// Constructor, getters and setters, Parcelable implementation
}
Actor.java
public class Actor implements Parcelable {
private String name;
private Movie movie;
// Constructor, getters and setters, Parcelable implementation
}
And now when I'm trying to write Movie into parcelable I get StackOverflowError:
java.lang.StackOverflowError
at java.util.concurrent.ConcurrentHashMap.putVal(ConcurrentHashMap.java:1012)
at java.util.concurrent.ConcurrentHashMap.putIfAbsent(ConcurrentHashMap.java:1535)
at java.lang.ClassLoader.getClassLoadingLock(ClassLoader.java:463)
at java.lang.ClassLoader.loadClass(ClassLoader.java:404)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at android.os.Parcel.writeParcelable(Parcel.java)
atcom.example.android.data.model.Actor.writeToParcel(Actor.java:58)
at android.os.Parcel.writeTypedList(Parcel.java:1106)
at com.example.android.data.model.Movie.writeToParcel(Movie.java:70)
I understand that here is problem with Nested classes, because when it tries to write Movie into Parcel, it tries to write Actor, but in Actor it tries to write Movie again.
QUESTION
How to avoid problem with nested classes?
Don't store the
Movie
inside theActor
. The two-way relationship between them is creating the error.Also, it doesn't even make sense that the
Actor
should store aMovie
. A real life actor can be in many movies, or none, or maybe they only do TV acting.Implement an Externalizable instead. Then use writeObject to serialize the references with account for object identity.
Java serialization protocol was designed to handle circular interdependencies between objects. Parcelables do not support those by design — attempting to hack in such support would pointlessly duplicate work, already done by creators of
ObjectInputStream
andObjectOutputStream
. Note, that I am not suggesting to implement Serializable (which is slow, because of being reflection-based), but rather implementing Externalizable, which is basically the same thing as Parcelable, except it plays well with serialization.ObjectOutputStream
itself is neither Serializable nor Parcelable, but you can direct it toByteArrayOutputStream
and pass resulting byte array around:And here is how your classes would look now:
Actor:
Movie:
I have just tested on my device and was able to successfully pass cross-referencing Movie/Actor across Activities via Intent.
This will create an infinite loop while writing the
Movie
object to aParcelable
, if you really need the reference to theMovie
from within theActor
you could try adding an ID to theMovie
class and give this ID to theActor
, later you could use this ID to track the correspondingMovie
, altho Im not sure if this still meets your requirements. Anyway, using a circular reference is strongly disencouraged in OO languages.