Implement parcelable interface using Gson - android

I'm trying to implement the parcelable interface using Gson. The idea is to create a json string (using gson) and write it to the parcel object.
Could it be a correct way to implement the interface?
The only problem I've encountered is when I deserialize the object. Actually, I use gson to recreate the object.
private MyClass(Parcel in) {
String json = in.readString();
Gson gson = new Gson();
gson.fromJson(json, getClass());
}
The problem is that the fromJson function returns an object that is the object the constructor should create.
The last line of code should be something like
this=gson.fromJson(json, getClass());
So, if this is a correct way to implement Parcelable, how could I solve this problem?

You should read more carefully the Parcelable javadoc. It contains everything you need.
As quoted in the docs :
Interface for classes whose instances can be written to and restored
from a Parcel. Classes implementing the Parcelable interface must also
have a static field called CREATOR, which is an object implementing
the Parcelable.Creator interface.
So you should have the writeToParcel method declared and also use a creator that will produce instances of your class from a Parcel.
The private constructor is an additional helper that you can use to set the value of the fields of an object given a parcel, but not the object itself. In Java, this is a right value, and can't be assigned.
BTW, the goal of parcelisation is to be provide a short term fast serialization process. You should, generally speaking, use a fast and compact data format when you use parcelisation. JSON is not a candidate of choice, but it will work.

Related

How Gson is filling values in private member data?

We can use gson for parsing JSON response and save our time. I have used this in numerous projects. What question came in my mind is even if we declare variable final, gson can fill that variables value.
Now this something strange and conflicting with OOP principals. How can any other thing except that class can access those private variables?
Is there any principal or concept which does this, probably as a part of Serialization or something like that ?
Also one more thing, in case of making it Parcelable we always have one parameterised constructor. At that time how Gson can create object of our class in absence of default constructor?
Gson is using Java "Reflection" for accessing the private fields of other class.

Implementing both Serializable and Parcelable interfaces from an object in Android - conflict

I have an object that i must save to file for reuse. The class of this object already implements Parcelable for use in intents. My knowledge of saving an object to file says to implement Serializable, but when i do, i get an error in the class that contains this object at the putExtra method of an intent because both Serializable and Parcelable have this method.
Is there a way to avoid this, or just a way that i can save my object state and reload it easily?
I have looked at a few articles and i feel no more informed about how i should be saving my object.
Thanks in advance
I believe that Parcelable and Serializable both reaches the same goal in different ways and with different performances. Given that, if some class in your object hierarchy alread implements the Parcelable interface, you can override its writeToParcel method, call the super for it (so the members of the super classes will be written to the parcel if they were implement that way) and then, you should write your attributes to the parcel, always keeping in mind that the order you use to save them is the order you will use to retrieve them latter (FILO data structure)
EDIT
Just cast your object where it complains and tells about the conflict to the class you want to use as described here: https://stackoverflow.com/a/13880819/2068693
I don't know that you can implement both Serializable and Parcelable together but for convert a class from Serializable to Parcelable you can use this plugin:
Android Parcelable Code generator.
First remove implement Serializable then with ALT + Insert and click on Parcelable you can generate your class.
You have options other than Serializable, but that may meet other requirements such as avoiding library dependencies. You can write objects to file using JSON or XML, which has the advantage of being readable. You may also need to consider versioning - what happens when you have files that need to be read by a class that contains a new field. Persistence brings with it some issues you probably don't have passing Bundles/Intents back and forth.
If you choose Serializable I'd recommend structuring your objects so they can be written to and read from a Bundle. Using a static MyObject.make(Bundle) method and an instance Bundle save() method keeps all the constants and read/write in a single location.

Android: convert Parcelable to JSON

I am working with socket.io library which emits messages to the socket.io server. The server expects JSON objects, arrays, etc. My original implementation used JSONOject and JSONArray datatypes. However, I would like to switch to using classes generated via Parceler library. The classes generated with library's annotations can be wrapped into Parcels. It seems like a very convenient way of managing such communication. However, is there a way to convert Parceler's class or a Parcel class into a JSON string or JSONObject/Array?
GSON library supports toJson method and I know that Retrofit does some magic with Parcels, JSON, and GSON.
i guess this will help you,
Create a class with getters and setters method for example
class A
{
int b;
void setb(int x){this.b = x;}
int getb(){return this.b}
}
than you can create json from the object of this class:
new Gson().toJson(a)
Or object from json:
a = new Gson().fromJson(data, A.class);

Implementing Parcelable interface on polymorphic arrays

I have an array of type named ItinerarySegment, and this type has subclasses: WalkSegment, BusSegment etc.
public interface ItinerarySegment
{
}
public class WalkSegment implements ItinerarySegment
{
}
public class BusSegment implements ItinerarySegment
{
}
What sort of strategy should I follow when making the array of ItinerarySegment parcelable? The main concern here is how it will be used later when re-constructing the array via the createTypedArray method (prepared by writeTypedArray method).
In which the createTypedArray method take a Creator field parameter. The problem lies here...Where should the Creator field be defined? (in ItinerarySegment, WalkSegment, or BusSegment?).
public static final Creator<Typename> CREATOR = new Parcelable.Creator<Typename>()
{
public Typename createFromParcel(Parcel in)
{
return new Typename(in);
}
public Typename[] newArray(int size)
{
return new Typename[size];
}
};
If I make ItinerarySegment an abstract class and define the Creator field's method, then the subsequent subclasses's data will be lost since neither of their constructors are called with the Parcel parameter, instead ItinerarySegment's constructor will be called.
constructor(Parcel in);
If I make WalkSegment define Creator field, then BusSegment would have a problem.
Any clarification needed?
In order to do this using writeTypedArray() and createTypedArray() you would need to make ItinerarySegment an abstract class, not an interface. ItinerarySegment would need to implement Parcelable and it would need to have a CREATOR defined that would be called to unmarshall the Parcel and create new objects. Derived classes would also need to implement the methods writeToParcel(), describeContents() and the CREATOR.
NOTE: Because writeTypedArray() does NOT write the type of the object into the Parcel, you will need to do this yourself. Here's 2 possible ways:
The writeParcel() method of each derived class would have to write something to the Parcel at the very beginning that identifies its type (a String or int value).
The writeParcel() method of each derived class would have to call super.writeToParcel() before writing anything to the Parcel. In the ItinerarySegment.writeToParcel() method you could figure out what type of derived class it is and write something to the Parcel that identifies its type (a String or int value).
The CREATOR in ItinerarySegment would first read the identifier from the Parcel and then using that, determine which type of object to instantiate. It would then call the corresponding object's CREATOR to actually instantiate the object and return that to its caller.
This basically works like an object factory, in which the base class knows how to instantiate different types of its own derived classes.
The downside of all this is that the abstract base class would have to know about all of its derived classes. I suppose you could also do this dynamically, by have all derived classes call a static method in the base class passing its "type" and CREATOR, which the base class would then store in an array to be used as needed.
All doable, but pretty complicated.
As an alternative you can use writeParcelableArray() and readParcelableArray(), where the class name of each object is written to the Parcel so that it knows which CREATOR to call when unmarshalling.
IMHO the only time to use writeTypedArray() and createTypedArray() is when all the objects in the array are instances of the same class, and you are writing more than a handful of them into the Parcel. In that case, you save the overhead of writing the class name into the Parcel for each object, as you know they are all the same. In this case you don't need to go through all the agony I described above because you know the type of all objects beforehand (no polymorphic types).
I realize this answer is probably more than a year late, but what the heck. Maybe it will help someone else ;-)

Android abstract arraylist parcelable

I have an arraylist of abstract objects(animals) and I'm trying to send and restore this array. The problem is that I need to give a creator when rebuilding the array, at this moment I'm passing a string that I check in the Animal creator and check what kind of animal I need to create.
I don't thing this is the most effective, so is there a better way to create a parcelable abstract array?
Here is a little demo project that describes the problem.
https://github.com/Evertvandenbruel/parcelable-abstract/tree/master/Parcelable-example/src/com/example/parcelable_example/model
Or is there an better to get the type of a parcelable object?

Categories

Resources