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
and ObjectOutputStream
. 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 to ByteArrayOutputStream
and pass resulting byte array around:
public static byte[] serialize(Externalizable object) {
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
ObjectOutputStream objectStream = null;
try {
objectStream = new ObjectOutputStream(buffer);
objectStream.writeObject(object);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (objectStream != null) {
try { objectStream.close(); } catch (IOException ignored) {}
}
}
return buffer.toByteArray();
}
public static <T extends Externalizable> T deserialize(byte[] bytes) {
ObjectInputStream objectStream = null;
try {
objectStream = new ObjectInputStream(new ByteArrayInputStream(bytes));
return (T) objectStream.readObject();
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException(e);
} finally {
if (objectStream != null) {
try { objectStream.close(); } catch (IOException ignored) {}
}
}
}
And here is how your classes would look now:
Actor:
class Actor implements Externalizable {
private String name;
private Movie movie;
public Actor(String name, Movie movie) {
this.name = name;
this.movie = movie;
}
// required by Externalizable contract
public Actor() {
}
@Override
public void readExternal(ObjectInput input) throws IOException, ClassNotFoundException {
name = input.readUTF();
movie = (Movie) input.readObject();
}
@Override
public void writeExternal(ObjectOutput output) throws IOException {
output.writeUTF(name);
output.writeObject(movie);
}
...
}
Movie:
class Movie implements Externalizable {
private List<Actor> actors;
private int year;
public Movie(int year) {
this.year = year;
actors = new ArrayList<>();
}
public void addActors(Actor... actors) {
Collections.addAll(this.actors, actors);
}
// required by Externalizable contract
public Movie() {
}
@Override
@SuppressWarnings("unchecked")
public void readExternal(ObjectInput input) throws IOException, ClassNotFoundException {
year = input.read();
actors = (List<Actor>) input.readObject();
}
@Override
public void writeExternal(ObjectOutput output) throws IOException {
output.write(year);
output.writeObject(actors);
}
...
}
I have just tested on my device and was able to successfully pass cross-referencing Movie/Actor across Activities via Intent.