Fragment crashes with Parcel: unable to marshal value error when onPause method is called
Asked Answered
Q

2

13

I have been developing android apps for a while now but only recently gotten into Fragments and hence I run into a lot of problems learning how to work with them. One of the activities in my applications has four different fragments, each of which displays a list of items to the user. Each fragment is created at first and is only shown once selected and hidden when another tab is selected. Once each of these fragments are created an ArrayList of JSONObjects is passed as an argument to the fragment as follows

            ft = fm.beginTransaction();

            if(currentFragment !=null){
                ft.hide(currentFragment);
            }
            if(whereFragment !=null){
                ft.show(whereFragment);
            }else{
                if(mPlaceList.size()>0){

                Bundle bundle = new Bundle();
                bundle.putSerializable("array", mPlaceList);
                whereFragment = new WhereFragment();
                whereFragment.setArguments(bundle);
                ft.add(R.id.newpost_container,whereFragment, "whereFragment");
                }
            }
            ft.commit();
            currentFragment = whereFragment;

The arraylist is received in the fragment and everything works just fine.

actList = (ArrayList<JSONObject>) getArguments().getSerializable("array");
doingAdapter = new DoingAdapter(getActivity(), actList);
actListView.setAdapter(doingAdapter);

There is a button in the parent activity that launches the device camera. Once that happens and the onPause method in the fragment is called the application crashes and I get this error in my Logcat

Logcat:

    06-23 17:51:31.190: E/ACRA(29221): com.parspake.anar fatal error : Parcel: unable to marshal value {"type":"act","id":"5327f9827f49143f3a001c76","title":"خونه","actType":"where"}
06-23 17:51:31.190: E/ACRA(29221): java.lang.RuntimeException: Parcel: unable to marshal value {"type":"act","id":"5327f9827f49143f3a001c76","title":"خونه","actType":"where"}
06-23 17:51:31.190: E/ACRA(29221):  at android.os.Parcel.writeValue(Parcel.java:1235)
06-23 17:51:31.190: E/ACRA(29221):  at android.os.Parcel.writeList(Parcel.java:622)
06-23 17:51:31.190: E/ACRA(29221):  at android.os.Parcel.writeValue(Parcel.java:1195)
06-23 17:51:31.190: E/ACRA(29221):  at android.os.Parcel.writeMapInternal(Parcel.java:591)
06-23 17:51:31.190: E/ACRA(29221):  at android.os.Bundle.writeToParcel(Bundle.java:1619)
06-23 17:51:31.190: E/ACRA(29221):  at android.os.Parcel.writeBundle(Parcel.java:605)
06-23 17:51:31.190: E/ACRA(29221):  at android.support.v4.app.FragmentState.writeToParcel(Fragment.java:132)
06-23 17:51:31.190: E/ACRA(29221):  at android.os.Parcel.writeTypedArray(Parcel.java:1102)
06-23 17:51:31.190: E/ACRA(29221):  at android.support.v4.app.FragmentManagerState.writeToParcel(FragmentManager.java:368)
06-23 17:51:31.190: E/ACRA(29221):  at android.os.Parcel.writeParcelable(Parcel.java:1254)
06-23 17:51:31.190: E/ACRA(29221):  at android.os.Parcel.writeValue(Parcel.java:1173)
06-23 17:51:31.190: E/ACRA(29221):  at android.os.Parcel.writeMapInternal(Parcel.java:591)
06-23 17:51:31.190: E/ACRA(29221):  at android.os.Bundle.writeToParcel(Bundle.java:1619)
06-23 17:51:31.190: E/ACRA(29221):  at android.os.Parcel.writeBundle(Parcel.java:605)
06-23 17:51:31.190: E/ACRA(29221):  at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:2096)
06-23 17:51:31.190: E/ACRA(29221):  at android.app.ActivityThread$StopInfo.run(ActivityThread.java:2918)
06-23 17:51:31.190: E/ACRA(29221):  at android.os.Handler.handleCallback(Handler.java:615)
06-23 17:51:31.190: E/ACRA(29221):  at android.os.Handler.dispatchMessage(Handler.java:92)
06-23 17:51:31.190: E/ACRA(29221):  at android.os.Looper.loop(Looper.java:137)
06-23 17:51:31.190: E/ACRA(29221):  at android.app.ActivityThread.main(ActivityThread.java:4827)
06-23 17:51:31.190: E/ACRA(29221):  at java.lang.reflect.Method.invokeNative(Native Method)
06-23 17:51:31.190: E/ACRA(29221):  at java.lang.reflect.Method.invoke(Method.java:511)
06-23 17:51:31.190: E/ACRA(29221):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
06-23 17:51:31.190: E/ACRA(29221):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608)
06-23 17:51:31.190: E/ACRA(29221):  at dalvik.system.NativeStart.main(Native Method)

I have been looking around in stackoverflow and I do see some questions with issues similar to mine, however I can't seem to take anything from any of them that can help me with my situation. I do get the gist of the issue with the fragment trying to save its state and not being able to serialize my json objects but it would be great if someone could help me work with either Serializable or Parcelable interfaces to fix my issue, that would be great. Also I have implemented Serializable in both fragment and activity as it has been suggested by others.

Qualifier answered 23/6, 2014 at 13:44 Comment(0)
Q
4

Well I managed to figure a way out of this, it may not be the most standard of way of doing things but it actually solved my problem and might help others to some extent.

What I did was instead of converting the JSONArray that was received from the API into a JSON arraylist and then sending it to the fragment, I converted the JSON array to string and sent it along with the bundle.

                ft = fm.beginTransaction();
                if(currentFragment !=null){
                    ft.hide(currentFragment);
                }
                if(doingFragment !=null){
                    ft.show(doingFragment);
                }else{
                    if(mActList.size()>0){
                    Bundle bundle = new Bundle();
                    bundle.putString("array", jArrayWhat.toString());
                    doingFragment = new DoingFragment();
                    doingFragment.setArguments(bundle);
                    ft.add(R.id.newpost_container,doingFragment, "doingFragment");
                    }
                }
                ft.commit();

In the fragment I received the bundle and converted the string into JSONArray.

    jsonActList = new JSONArray(getArguments().getString("array"));

Then I iterated through the JSONArray and converted it into a JSONObject ArrayList. And in order to keep the changes made to the my list after the fragment has been in use, I converted the ArrayList back into a JSONArray and saved it.

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    JSONArray jArray = new JSONArray(Arrays.asList(actList));
    outState.putString("jsonArray", jArray.toString());
}

Now that the state was saved it could easily be restored in the onCreateView method as follows

 if ((savedInstanceState != null)
                   && (savedInstanceState.getSerializable("jsonArray") != null)) {
             jsonActList = new JSONArray(savedInstanceState.getString("jsonArray"));
             positionList = (ArrayList<String>) savedInstanceState.getSerializable("positionList");
    }

This way I wouldn't have to deal with the issue of making my JSONObjects Serializable or Parcelable

Qualifier answered 24/6, 2014 at 7:53 Comment(0)
J
35

If you already get data you need, then just remove data from bundle.

// get your data
Bundle bundle = getArguments();
JSONObject myData = (JSONObject) bundle.getSerializable("myData");

// remove it
getArguments().remove("myData");
Jann answered 2/2, 2015 at 13:56 Comment(4)
That does sound like a great way to go about itQualifier
Im pretty sure now that by purging each value from my bundle I no longer receive marshal errors, but could someone please explain why must each value be removed even if the bundle is never touched again after being read from? Very curious!Hokeypokey
i was getting this error when i start some activity, but this one worked. thanksHappen
Great answer, I wasn't abe to fix that error until this answer. Why is necessary to remove the data from the bundle?Diarchy
Q
4

Well I managed to figure a way out of this, it may not be the most standard of way of doing things but it actually solved my problem and might help others to some extent.

What I did was instead of converting the JSONArray that was received from the API into a JSON arraylist and then sending it to the fragment, I converted the JSON array to string and sent it along with the bundle.

                ft = fm.beginTransaction();
                if(currentFragment !=null){
                    ft.hide(currentFragment);
                }
                if(doingFragment !=null){
                    ft.show(doingFragment);
                }else{
                    if(mActList.size()>0){
                    Bundle bundle = new Bundle();
                    bundle.putString("array", jArrayWhat.toString());
                    doingFragment = new DoingFragment();
                    doingFragment.setArguments(bundle);
                    ft.add(R.id.newpost_container,doingFragment, "doingFragment");
                    }
                }
                ft.commit();

In the fragment I received the bundle and converted the string into JSONArray.

    jsonActList = new JSONArray(getArguments().getString("array"));

Then I iterated through the JSONArray and converted it into a JSONObject ArrayList. And in order to keep the changes made to the my list after the fragment has been in use, I converted the ArrayList back into a JSONArray and saved it.

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    JSONArray jArray = new JSONArray(Arrays.asList(actList));
    outState.putString("jsonArray", jArray.toString());
}

Now that the state was saved it could easily be restored in the onCreateView method as follows

 if ((savedInstanceState != null)
                   && (savedInstanceState.getSerializable("jsonArray") != null)) {
             jsonActList = new JSONArray(savedInstanceState.getString("jsonArray"));
             positionList = (ArrayList<String>) savedInstanceState.getSerializable("positionList");
    }

This way I wouldn't have to deal with the issue of making my JSONObjects Serializable or Parcelable

Qualifier answered 24/6, 2014 at 7:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.