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 Serializable
interface 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 a Bundle
so 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 counterpart getLastNonConfigurationInstance()
will be a much more efficient method of passing that object around if you are in the context of an Activity
. If you are using the Fragment
APIs, take a look at the setRetainInstance()
method as well.
HTH
For me it looks strange because Java (multidimensional) arrays are serializable by default (or am I wrong?). But it seems that, at least in Android, something is different with this.
You anyways should pass using Parcelable. It's somewhat tedious to implement, but faster than Serializable... Here is a howto: Passing multidimensional array using Serializable
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.