0

I am developing simple travel agent android application. When application starts it loads list of cities, in the next activity user will see source and destination spinners, once user selects proper source and destination, it will take to third activity, it displays available travels if user selects one it takes to fourth activity in which user selects seat and continues to book ticket. In order to maintain complete user session I am maintaining a UserSession class, which is as follows (removing unnecessary logic in the code which is irrelevant to problems)

    public class UserSession implements Parcelable {
        List<City> citiesList;
        HashMap<String, City> cityMap; // Map city name to code
        RouteSearchResult searchedRoutes;
        String sourceCity;
        String destinationCity;
        LocalStop selectedBoardingPoint;
        LocalStop selectedArrivalPoint;

        @Override
        public void writeToParcel(Parcel parcel, int flags) {
            try {
                parcel.writeList(citiesList);
                parcel.writeMap(cityMap);
                parcel.writeValue(searchedRoutes);
                parcel.writeString(sourceCity);
                parcel.writeString(destinationCity);
                parcel.writeValue(selectedBoardingPoint);
                parcel.writeValue(selectedArrivalPoint);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    public class City implements Parcelable {
        String cityName;
        String cityId;
        @Override
        public void writeToParcel(Parcel parcel, int flags) {
            parcel.writeString(cityName);
            parcel.writeString(cityId);
        }
    }
    public class RouteSearchResult {
            City source;
            City destination;
            String date;
            List<RouteDetails> routeDetails;
    }

I have the following problems 1) I am getting run time exception while writing

W/System.err(  817): java.lang.RuntimeException: Parcel: unable to marshal value com.travelagent.City@40605878
W/System.err(  817):    at android.os.Parcel.writeValue(Parcel.java:1132)
W/System.err(  817):    at android.os.Parcel.writeList(Parcel.java:519)
W/System.err(  817):    at com.travelagent.UserSession.writeToParcel(UserSession.java:201)
W/System.err(  817):    at android.os.Parcel.writeParcelable(Parcel.java:1151)

2) I commented parcel.writeList(citiesList); statement to see if I get any more problems, I got similar problem with parcel.writeValue(searchedRoutes);

I have following questions, 1) How to make a list of custom objects as parcelable? 2) Is it mandatory to make custom class like City also parcelable, which is part of actual class to be parceled. 3) Is there any approach to solve this kind of problems like passing user session to all activities.

Please help, I searched, but I couldn't find appropriate solution to make custom class parcelable.

Srinivas
  • 553
  • 9
  • 21

1 Answers1

1

My understanding is that you shouldn't use Parcels for this. From the android documentation on Parcels:

Parcel is not a general-purpose serialization mechanism. This class (and the corresponding Parcelable API for placing arbitrary objects into a Parcel) is designed as a high-performance IPC transport. As such, it is not appropriate to place any Parcel data in to persistent storage: changes in the underlying implementation of any of the data in the Parcel can render older data unreadable.

What you should do is create two static methods for each class you want to transfer to the next activity. Call one of them toBundle() and one of them fromBundle(). The first converts a given instance of you class to a bundle while the second creates a new instance of your class from a bundle. Every time you need to pass an object on to the next Activity, just bundle it up using the toBundle() method and add it to the Intent you're using to start the next Activity. In the next Activity, you can recreate the object by calling fromBundle().

Kurtis Nusbaum
  • 30,445
  • 13
  • 78
  • 102
  • Thank you. I could solve unmarshal problem. The mistake is, in the read parcel function, I didn't create objects for types List and Map, I have to create. This fixed the problem. With parcelable/bundle approach, if we have a list of 100 custom objects, this will make it costly to write to bundle/parcel and read from bundle/parcel. So to avoid this problem I made UserSession's elements static, this can avoid additional copies, but I don't know penalty of this approach. – Srinivas Oct 22 '11 at 21:47
  • I do not think there is other clean way doing this. Basically keeping the data to pass around in statics is similar to marshalling and gives you the full control of their state. – blacharnia May 03 '14 at 08:09