Search code examples
androidserializationandroid-fragmentsbitmapandroid-bundle

Why can I pass a serializable with a bitmap through a Bundle but get an error when the system tries to serialize it?


So I have a class, with an image that implements serializable:

public class Contact implements Serializable
{
    ...
    public static final String CONTACT_KEY = "contactKey";
    private transient Bitmap mImage;
    ...
}

I pass this to a fragment:

Bundle bundle = new Bundle();
final FragmentManager fragmentManager = getFragmentManager();

// Load the fragment
Fragment contactFragment = new ContactFragment();
contactFragment.setArguments(bundle);
fragmentManager.beginTransaction()
            .replace(R.id.contactContainer, headerFragment, "ContactFragment")
            .commit();

And pull the image out (successfully) and use it:

public class ContactFragment extends Fragment
{
    private static final String TAG = "ContactFragment";

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState)
    {
        Bundle arguments = getArguments();
        if (arguments != null)
        {
            Contact contact = (Contact) arguments.getSerializable(Contact.CONTACT_KEY);
            ViewGroup view = (ViewGroup)inflater.inflate(R.layout.contact, container, false);
            if (view != null && contact != null)
            {
                ImageView imageView = (ImageView) view.findViewById(R.id.contactImage);
                if (imageView != null)
                {
                    if (contact.hasImage())
                    {
                        imageView.setImageBitmap(contact.image());
                    }
                }
            }
        }
    }
}

BUT when I background my app I receive a runtime exception from the system:

Process: my.package, PID: 11680
    java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = my.package.Contact)
            at android.os.Parcel.writeSerializable(Parcel.java:1316)
            at android.os.Parcel.writeValue(Parcel.java:1264)
            at android.os.Parcel.writeArrayMapInternal(Parcel.java:618)
            at android.os.Bundle.writeToParcel(Bundle.java:1692)
            at android.os.Parcel.writeBundle(Parcel.java:636)
            at android.app.FragmentState.writeToParcel(Fragment.java:132)
            at android.os.Parcel.writeTypedArray(Parcel.java:1133)
            at android.app.FragmentManagerState.writeToParcel(FragmentManager.java:373)
            at android.os.Parcel.writeParcelable(Parcel.java:1285)
            at android.os.Parcel.writeValue(Parcel.java:1204)
            at android.os.Parcel.writeArrayMapInternal(Parcel.java:618)
            at android.os.Bundle.writeToParcel(Bundle.java:1692)
            at android.os.Parcel.writeBundle(Parcel.java:636)
            at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:2467)
            at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3084)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5001)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
     Caused by: java.io.NotSerializableException: android.graphics.Bitmap
            at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1364)
            at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671)
            at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
            at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
            at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:979)
            at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:368)
            at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1074)
            at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1404)
            at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671)
            at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
            at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
            at android.os.Parcel.writeSerializable(Parcel.java:1311)
            at android.os.Parcel.writeValue(Parcel.java:1264)
            at android.os.Parcel.writeArrayMapInternal(Parcel.java:618)
            at android.os.Bundle.writeToParcel(Bundle.java:1692)
            at android.os.Parcel.writeBundle(Parcel.java:636)
            at android.app.FragmentState.writeToParcel(Fragment.java:132)
            at android.os.Parcel.writeTypedArray(Parcel.java:1133)
            at android.app.FragmentManagerState.writeToParcel(FragmentManager.java:373)
            at android.os.Parcel.writeParcelable(Parcel.java:1285)
            at android.os.Parcel.writeValue(Parcel.java:1204)
            at android.os.Parcel.writeArrayMapInternal(Parcel.java:618)
            at android.os.Bundle.writeToParcel(Bundle.java:1692)
            at android.os.Parcel.writeBundle(Parcel.java:636)
            at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:2467)

Presumably as it tries to preserve my fragments arguments.

I know I shouldn't be trying to serialize a bitmap like this, but my question is WHY DOES THIS WORK? Is android doing some kind of optimization?

In both cases the Contact is serialized so what's going on?


Solution

  • Caused by: java.io.NotSerializableException: android.graphics.Bitmap

    Ok so to clarify bitmaps are not serializable i.e. they can't be broken down and saved to disk (hard cache).

    In the first case, it will be using a soft cache like a Map maybe, so the bitmap can be saved in memory. (soft cache)

    When you background your app, the system then tries to save your data to disk so it has to serialize the things and thats when you get the crash.

    Make sense?