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.
Related
I used to use Serializable objects to save them in filesytem and read them in order to do whatever I want. But Serialization is slow when you have to pass data between activities, so I read than it's recommanded to use Parcelable. Then I did it and yeah it's faster ! But now, I have a little problem. Since Parcelable is optimized for IPC, then they aren't serializable and can't be saved into a file. So I would to know if it's possible to do it.
Also, If I decide to implement both Parcelable and Serializable interface for my class, but only use the Parcelable to pass data between my activities, I would be able to save the class into a file. But I guess than since I use serializable (only to save, not to pass data), this is not a good idea hum ?
I thought too to use Gson library, to serialize data from class, and save the JSON into a file, and reuse Gson to deserialize JSON to get my Parcelable object. Does it seems to be a good idea ? What about performance ?
Thanks to all for your answers!
J.
Just do context.getFilesDir() and use a java.io.ObjectInputStream and java.io.ObjectOutputStream.
Also, with regard to "Parcelable not now serializable". This doesn't entirely make a lot of sense since Parcelable in an interface, not a class you extend.
So,
class MyClass implements Parcelable, Serializable {
}
should work just fine. Once you read and write the object to the file system, the Parcelable interface will still work. It's only an interface.
I have to admit I haven't tried it, but it's what I wrote today and I will be writing the unit test tomorrow.
Hope this helps.
Here's another approach if, as you say there is a conflict between the Parcelable and Serializable interfaces. (Again, that doesn't make sense, but I'll trust you until I finish my unit tests tomorrow)...
Think about this:
Parcel p = Parcel.obtain();
p.writeValue(asset);
p.setDataPosition(0);
byte [] b = p.marshall();
p.recycle();
OOPS, just read the javaDoc for marshall() and it says DO NOT STORE TO DISK. It also says, "Use standard serialization to store to disk" (paraphrase).
So, my first answer should do it for you.
Did you try to use shared preferences? If you need to store key values. Moreover it'll be an XML.
I have an object which has the following class fields:
int, int, String, MyDatabaseType (custom object), List < MyDatabaseDetail > (array list of custom objects)
Is it possible for me to pass this through an intent/bundle?
I've played around a little bit with serializable and parcelable, but I couldn't get it working. Would I need to make all of custom object types parcelable, instead of just the main one that I want to pass?
Surely there is a better way?
When you pass data in an intent, it must be Parcelable. That is because the intent may passed to a different application, and thus a different VM. As your object may be crossing process boundaries, it needs a mechanism that will allow it to be saved/restored. This is analogous to passing data via a web service call (in this case, the object is "flattened" to something like either XML or JSON).
Even if the intent stays within your application, parcelability allows the object to survive even if Android chooses to kill/re-launch your application, which can happen if memory is running low.
Serialization can be used instead of parcelization, however parcelization is more efficient.
You can make your class Parcelable if it contains variables that are not serializable. If all variables inside your class are primitive or serializable or you can make them serializable, it's easy enough to do it.
You can follow this guide: http://developer.android.com/reference/java/io/Serializable.html
In most cases, all you have to do is to make your class implement Serializable interface and add the following line in your class:
private static final long serialVersionUID = 0L;
(read more in the guide above).
From android documentation:
NOTE: Seeing Parcelable might have triggered the question, why is Android not using the built-in Java serialization mechanism? It turns out that the Android team came to the conclusion that the serialization in Java is far too slow to satisfy Android’s interprocess-communication requirements. So the team built the Parcelable solution. The Parcelable approach requires that you explicitly serialize the members of your class, but in the end, you get a much faster serialization of your objects.
So we know that Parcelable is actually better than Serializable but, on the other hand,
Also realize that Android provides two mechanisms that allow you to pass data to another process. The first is to pass a bundle to an activity using an intent, and the second is to pass a Parcelable to a service. These two mechanisms are not interchangeable and should not be confused. That is, the Parcelable is not meant to be passed to an activity. If you want to start an activity and pass it some data, use a bundle. Parcelable is meant to be used only as part of an AIDL definition.
Ok man, but I need to pass a custom object list to my activity!So into the bundle I still have to put either a parcelable or a serializable!
For now I did this way:
public class MyObject implements Serializable{
and to pass:
Bundle b = new Bundle();
b.putSerializable("objList", anArrayListWithMyObjectElements);
intent.putExtra("objList", b);
as ArrayList implements Serializable too it works fine...but I don't see the point of using a bundle this way...but android tells me to not use Parcelable for activity communication...what's the correct answer??
In my exprience, I strongly suggest using Parcelable when you can, IPC or not. It's Android's de facto replacement for Java's Serializable, and it's more optimized.
If you need help on how to parcel an object, let me know.
When bundling an object for later retrieval do I have to bundle objects within those objects?
For example, if I have an object that represents a player in a card game and within that I instantiate an object that represents the player's hand, do I have save the inner object to the bundle or is that automatically included with the outer one?
You cannot bundle any old Object, it has to be a String or a primitive such as boolean, integer, 'byte' or an array of these simple things. In this case yes, the contents of a String[] array are saved with the Bundle.
For more complex structures you can use implement the Parcelable in your object class, but it will be up to you to make sure the object saves all necessary information to it's Parcel and restores it.
java.ui.Serializable is something worth checking. It pretty much automates bundling class and its member variables as long as your class and all required members implement Serializable interface too.
http://www.tutorialspoint.com/java/java_serialization.htm
Is it possible for Activity(s) to communicate using user defined object?
p.s.
So far as I know, when I want Activity(s) to communicate to each other, I have to use primitive type of objects, such as int, String, boolean,...etc.
We don't use Serializable, Parcelable and static class.
If talkin about extras when caling intents, you can implement Serializable or Parcelable interface in your objects to pass them through.
You can also put that object into own implementation of Application class and access it in Activity or Service class as described in my other answer. But please keep in mind, that sharing state in that manner may be a sign of more general problem in your design.
You have a few options:
1.You could wrap the more complex structure in a class that implements the Parcelable interface, which can be stored in an extra.
2.You could wrap the more complex structure in a class that implements the Serializable interface, which can be stored in an extra
3.You use static data members to pass stuff around, since they are all in the same process
4.You use external storage (file, database, SharedPreferences)
5.As the person who just posted noted, use a common component, such as a custom Application or a local Service
What you do not want to do is pass big stuff via extras. For example, if you are creating an application that grabs pictures off the camera, you do not want to pass those in extras -- use a static data member (icky as that sounds). Intents are designed to work cross-process, which means there is some amount of data copying that goes on, which you want to avoid when it is not necessary for big stuff.
Answer copy from here
Intent myintent = new Intent(Info.this, GraphDiag.class).putExtra("<StringName>", value);
startActivity(myintent);
use the above code in parent activity
and in child activity
int s= getIntent().getIntExtra("<StringName>");
in the same u retrive the float,char,String values