Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 289
Nami Alejandro Salimi Avatar asked Jun 23 '14 13:06

Nami Alejandro Salimi


2 Answers

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");
like image 77
Lee Jeongmin Avatar answered Oct 25 '22 02:10

Lee Jeongmin


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

like image 35
Nami Alejandro Salimi Avatar answered Oct 25 '22 02:10

Nami Alejandro Salimi