I know there are many questions on storing ArrayList
s in Bundle
s here on stackoverflow, but even after reading many of them and the documentation, I do not understand the problem I describe below. I am not so much asking for help with solving this particular programming issue, because I have a "solution", but rather want to understand why I get the error and why my "solution" works.
The standard PointF
class is (unfortunately) not serializable, which is why I extend that class and (hopefully correctly) implement the code for the serialization of pointF
s as follows:
class PointFSerializable extends PointF implements Serializable
{
public PointFSerializable(PointF pointF) {
super(pointF.x, pointF.y);
}
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
out.writeFloat(x);
out.writeFloat(y);
}
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
float x = in.readFloat();
float y = in.readFloat();
set(x,y);
}
private void readObjectNoData() throws ObjectStreamException {
set(0f,0f);
}
}
Now I have a nested ArrayList
of such PointFSerializable
objects, which is serializable
because ArrayList
and PointFSerializable
are serializable, and which I can hence put into a Bundle bundle
as follows:
ArrayList<ArrayList<PointFSerializable>> drawingSerializable = new
ArrayList<ArrayList<PointFSerializable>>();
//populate the nested ArrayList
for([...]) {
ArrayList<PointFSerializable> strokeSerializable = new ArrayList<PointFSerializable>();
for([...]) {
strokeSerializable.add(new PointFSerializable(...));
}
drawingSerializable.add(strokeSerializable);
}
//Put it into the Bundle
bundle.putSerializable("Drawing", drawingSerializable);
In a different function I later retrieve the nested ArrayList
from the Bundle bundle
via getSerializable()
and a cast as follows:
ArrayList<ArrayList<PointFSerializable>> drawingSerializable = (ArrayList<ArrayList<PointFSerializable>>)bundle.getSerializable("Drawing");
Up to here everything works as expected, but now I want to loop over the drawingSerializable
:
for(ArrayList<PointFSerializable> strokeSerializable : drawingSerializable) {
for(PointFSerializable pointFSerializable : strokeSerializable) { //<--
[...]
}
}
In the line marked with the <--
I get a
java.lang.ClassCastException: android.graphics.PointF cannot be cast to com.cgogolin.myapp.PointFSerializable
which is what I don't understand.
I would have expected this error is strokeSerializable
were of tpye ArrayList<PointF>
, but, evidently it should not be, because I defined it to be of type ArrayList<PointFSerializable>
and if it were not of that type then I would have expected to already get an error in the outer for loop.
Now, in the body of the inner for loop I anyway want to cast the pointFSerializable
to PointF
. I can hence replace the problematic line by
for(PointF pointF : strokeSerializable) {
and then everything works as it should. But why?
Why, from bundle.getSerializable("Drawing");
, do I apparently getting back something that I can treat like an ArrayList<ArrayList<PointF>>
(which is not even a serializable object!) but not like an ArrayList<ArrayList<PointFSerializable>>
, even though I put an object of the latter type into the Bundle?
PointF is parcelable, which means you can put the standard PointF into a bundle. If a class is both serializable and parcelable, Android will defer to write and read to a parcel. What is happening is since you are not overriding the parceling method, Android parcels your object as a standard PointF. If you need the ability to serialize your class outside of that, make sure to override the methods required in the Parcelable interface.