I have two helper methods inside a custom View which are called by their Fragment:
public Bundle returnInstanceState() {
Bundle state = new Bundle();
state.putSerializable("colorData", colorData);
return state;
}
public void loadInstanceState(Bundle savedInstanceState) {
if(savedInstanceState.getSerializable("colorData") != null)
colorData = (int[][]) savedInstanceState.getSerializable("colorData");
}
The lifecycle of colordata:
private int[][] colorData;
protected void onSizeChanged (int w, int h, int oldw, int oldh)
{
width = w;
height = h;
screen = new int[width*height];
cellSize = 0;
if(firstLoad && h!= 0 && w!=0)
{
if(nWidth>nHeight)
colorData = new int[nWidth/(nHeight/170 - 1) + 1][170];
else
colorData = new int[nHeight/(nWidth/170 - 1) + 1][170];
firstLoad = false;
}
}
nWidth and nHeight are static int which represent the native resolution.
However once in a blue moon I am given a ClassCastException. Why?
From my tests it seems you can cast null to int[][] though thats not actually a goal of mine.
colorData is type int[][] and I never get a NullPointerException anywhere so as far as I can tell everything works except the act of casting Serializable to int[][] and only occasionally.
Here is a stack trace, though it isn’t of much use in this case:
java.lang.RuntimeException: Unable to start activity ComponentInfo{<MYPACKAGENAMEHERE>/<MYPACKAGENAMEHERE>.MusicVisualizerActivity}: java.lang.ClassCastException: [Ljava.lang.Object;
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1659)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1675)
at android.app.ActivityThread.access$1500(ActivityThread.java:121)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:943)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3701)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:624)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ClassCastException: [Ljava.lang.Object;
at <MYPACKAGENAMEHERE>.Visualization_Spectral$RenderView.loadInstanceState(Visualization_Spectral.java:95)
at <MYPACKAGENAMEHERE>.Visualization_Spectral.onCreateView(Visualization_Spectral.java:46)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:870)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1080)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1062)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1810)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:501)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1129)
at android.app.Activity.performStart(Activity.java:3791)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1632)
... 11 more
java.lang.ClassCastException: [Ljava.lang.Object;
at <MYPACKAGENAMEHERE>.Visualization_Spectral$RenderView.loadInstanceState(Visualization_Spectral.java:95)
at <MYPACKAGENAMEHERE>.visualization.Visualization_Spectral.onCreateView(Visualization_Spectral.java:46)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:870)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1080)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1062)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1810)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:501)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1129)
at android.app.Activity.performStart(Activity.java:3791)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1632)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1675)
at android.app.ActivityThread.access$1500(ActivityThread.java:121)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:943)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3701)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:624)
at dalvik.system.NativeStart.main(Native Method)
The
Serializableinterface if full of flaws and should be avoided whenever possible, especially in Android. From the looks of your code, your are only temporarily passing this object into aBundleso an Activity or other component can be recreated and, if nothing else, serializing the object will provide poor performance for such a temporary need.The API
onRetainNonConfigurationInstance()and its counterpartgetLastNonConfigurationInstance()will be a much more efficient method of passing that object around if you are in the context of anActivity. If you are using theFragmentAPIs, take a look at thesetRetainInstance()method as well.HTH