In this paper, the serializable and Parcelable serialization objects in Android are studied in detail as follows
Learning content:
1. The purpose of serialization
Two ways to serialize in 2.Android
Performance comparison of 3.Parcelable and serializable
How to use parcelable to serialize operations in 4.Android
The working principle of 5.Parcelable
6. Relevant examples
1. The purpose of serialization
1. Permanently save object Data (Save object data in a file, or disk
2. The object data is transmitted over the network through serialization (because the network transmission is transmitted as a byte stream). So the purpose of serialization is to convert the object data into the form of a byte stream.
3. Object data is passed between processes (the object data is passed between the activity, and the object data needs to be serialized in the current action). Deserialization is required in another activity to tell the data out.
4). The Java platform allows us to create reusable Java objects in memory. In general, however, these objects can exist only when the JVM is running, that is, the life cycle of these objects is not longer than the JVM's lifecycle (that is, each object is in the JVM), but in real-world applications, You may want to stop the JVM from running, but have to save some of the specified objects and re-read the saved objects in the future. This is the function that Java object serialization can achieve. (You can choose to save in the form of a database, or file)
5. When serializing an object, it is only serialized for a variable and not serialized for a method.
6. Between intent, the basic data types are directly related to the transfer, but once the data type is more complex, it needs to be serialized operation.
Two ways to implement serialization in 2.Android
1). Implements Serializable Interface (declare it)
A simple example of Serializable:
public class person implements serializable{
private static final long serialversionuid = -7060210544600464481l;
private String name;
private int age;
Public String GetName () {return
name;
}
public void SetName (String name) {
this.name = name;
}
public int getage () {return age
;
}
public void Setage (int age) {
this.age = age;
}
}
2). Implements Parcelable interface (not only need to declare, but also implement internal corresponding method)
A simple example of parcelable:
Note: The order in which data is written must be the same as the order in which the data is read.
public class book implements parcelable{private String bookname;
Private String author;
private int publishdate;
Public book () {} public String Getbookname () {return bookname;
} public void Setbookname (String bookname) {this.bookname = BookName;
Public String Getauthor () {return author;
} public void Setauthor (String author) {this.author = author;
public int getpublishdate () {return publishdate;
The public void setpublishdate (int publishdate) {this.publishdate = publishdate;
@Override public int describecontents () {return 0;
@Override public void Writetoparcel (Parcel out, int flags) {out.writestring (bookname);
Out.writestring (author);
Out.writeint (publishdate); public static final parcelable.creator<book> Creator = new creator<book> () {@Override public Bo
Ok[] NewArray (int size) {return new book[size]; @Override Public book Createfromparcel (Parcel in) {return new book (in);
}
}; Public book (Parcel in) {//If the element data is a list type: Lits = new arraylist<?> in.readlist (list), or null pointer exception. And the data types read out and written must be
Must be the same. If you do not want to serialize some of the keywords, you can use the transient keyword to decorate and static adornments.
BookName = In.readstring ();
Author = in.readstring ();
Publishdate = In.readint ();
}
}
We know that serializing a class in a Java application requires only the implementation of the Serializable interface, the serialization and deserialization of the system, but there's another way to do serialization in Android. That is to implement the Parcelable interface. It is also a unique interface in Android to implement serialization of classes. The reason is that Parcelable's performance is stronger than that of serializable. So in the vast majority of cases, Android is also recommended to use Parcelable to perform serialization operations on the class.
Performance comparison of 3.Parcelable and serializable
First of all, Parcelable's performance is stronger than the serializable reason I need to explain briefly
1). In the use of memory, the former is better than the latter in terms of performance
2. The latter produces a large number of temporary variables in the serialization operation (due to the use of the reflection mechanism) resulting in frequent calls to the GC, which is slightly less performance
3). Parcelable is based on IBinder as the carrier of information. The overhead is relatively small in memory, so when data transfer between memory, Android recommended the use of parcelable, since it is the advantages of parity in memory, then nature will have priority to choose.
4. When reading and writing data, the parcelable is read and write directly in memory, while serializable reads the data to the hard disk by using IO streaming.
However: Although parcelable performance is better than serializable, there are special circumstances that require the use of serializable instead of parcelable because parcelable cannot persist the data. So when you save data to disk, you still need to use the latter, because the former is not a good way to persist data. (The reason is that parcelable may be different in different versions of Android, so the persistence of data is still using serializable)
Speed test:
Test method:
1, by placing an object inside a bundle and then invoking the Bundle#writetoparcel (Parcel, int) method to simulate the process of passing an object to an activity, and then taking the object out.
2. Run 1000 times inside a loop.
3), two methods to run 10 times to reduce the memory collation, the CPU by other applications occupy and other situations interference.
4), the object that participates in the test is above related code
5. Testing on a variety of Android software and hardware environments
- LG Nexus 4–android 4.2.2
- Samsung Nexus 10–android 4.2.2
- HTC Desire Z–android 2.3.3
The result is as shown in figure:
Performance difference:
Nexus 10
Serializable:1.0004ms, parcelable:0.0850ms– 10.16 times times.
Nexus 4
serializable:1.8539ms–parcelable:0.1824ms– 11.8 times times.
Desire Z
Serializable:5.1224ms–parcelable:0.2938ms– 17.36 times times.
It can be concluded that parcelable is 10 times faster than serializable.
We can see from the relative comparison that the performance of parcelable is much better than that of serializable, so in order to serialize in Android, we need to choose the former as much as possible. It takes a lot of time to implement the internal methods in the Parcelable interface.
How to use parcelable to serialize operations in 4.Android
Having said so much, let's take a look at how Android can use Parcelable to implement serialization of classes.
The internal approach needs to be implemented when Implements parcelable:
1. Writetoparcel serializes the object data into a parcel object (after serialization becomes the parcel object.) so that the parcel container takes out the data.
2). Override the Describecontents method with the default value of 0
3). The public static final parcelable.creator<t>creator (converting the data in the parcel container into object data) requires two methods to be implemented:
3.1 Createfromparcel (remove the data from the parcel container and convert it.)
3.2 NewArray (int size) returns the size of the object's data
Therefore, it is not easy to realize parcelable. Implementing the Parcelable interface requires writing a large number of template code, which makes the object code difficult to read and maintain. The concrete example is the instance code above parcelable. No enumeration. (interested to see the Android Networkinfo source code, is about the network connection of additional information of a related class, the internal implementation of the serialization operation.)
The working principle of 5.Parcelable
Whether you read or write data, you need to use parcel as the middle tier to deliver the data. Parcel is related to the underlying C + +. It's all about using JNI. In the Java application layer, you create the parcel (Java) object First, Then the associated read and write operation is invoked. Take read and write 32 for int data:
Static Jint Android_os_parcel_readint (jnienv* env, Jobject clazz) {
parcel* Parcel = Parcelforjavaobject (env, Clazz) ;
if (parcel!= NULL) {return
parcel->readint32 ();
}
return 0;
}
The method invoked is the process of converting a parcel (Java) object into a parcel (C + +) object, and then being encapsulated in parcel to complete the serialization of the data by the underlying C + +.
status_t Parcel::writeint32 (int32_t val) {return writealigned (val);} Template<class t= "" > status_t parcel::writealigned (t val) {Compile_time_assert_function_scope (PAD_SIZE
(t) = = = sizeof (t));
if ((Mdatapos+sizeof (val)) <= mdatacapacity) {restart_write: *reinterpret_cast<t*> (Mdata+mdatapos) = Val;
return Finishwrite (sizeof (Val));
} status_t Err = Growdata (sizeof (Val));
if (err = = no_error) goto restart_write;
return err;
The true read and write process is done by the following source code. status_t Parcel::continuewrite (size_t desired) {//If shrinking, the A-adjust for any objects
New data size.
size_t objectssize = mobjectssize;
if (desired < mdatasize) {if (desired = 0) {objectssize = 0;
else {while (Objectssize > 0) {if (Mobjects[objectssize-1] < desired) break;
objectssize--;
}} if (Mowner) {//If the size is going to zero, just release the owner ' s data.
if (desired = = 0) {freedata (); Return no_eRror;
}//If There is a different owner, we need to take//posession.
uint8_t* data = (uint8_t*) malloc (desired);
if (!data) {merror = no_memory;
return no_memory;
} size_t* objects = NULL;
if (objectssize) {objects = (size_t*) malloc (objectssize*sizeof (size_t));
if (!objects) {merror = no_memory;
return no_memory;
}//Little hack to only acquire references on objects//We'll be keeping.
size_t oldobjectssize = mobjectssize;
Mobjectssize = objectssize;
Acquireobjects ();
Mobjectssize = oldobjectssize;
} if (Mdata) {memcpy (data, Mdata, mdatasize < desired? mdatasize:desired);
} if (objects && mobjects) {memcpy (objects, Mobjects, objectssize*sizeof (size_t));
}//alogi ("Freeing data ref of%p (pid=%d) \ n", this, Getpid ());
Mowner (This, Mdata, Mdatasize, Mobjects, Mobjectssize, Mownercookie);
Mowner = NULL;
Mdata = data;
Mobjects = objects; Mdatasize = (Mdatasize < desired) ?
mdatasize:desired;
ALOGV ("Continuewrite Setting data size of%p to%d\n", this, mdatasize);
mdatacapacity = desired;
Mobjectssize = Mobjectscapacity = Objectssize;
Mnextobjecthint = 0;
else if (mdata) {if (Objectssize < mobjectssize) {//Need to release refs on any objects we are dropping.
Const sp<processstate> proc (processstate::self ()); For (size_t i=objectssize i<mobjectssize; i++) {Const flat_binder_object* flat = Reinterpret_cast<flat_bi
Nder_object*> (Mdata+mobjects[i]); if (Flat->type = = binder_type_fd) {/would need to rescan because we have lopped
own = false;
} release_object (proc, *flat, this);
} size_t* objects = (size_t*) realloc (mobjects, objectssize*sizeof (size_t));
if (objects) {mobjects = objects;
} mobjectssize = Objectssize;
Mnextobjecthint = 0;
//We own the data, so we can just do a realloc (). if (Desired > MdatacapaciTy) {uint8_t* data = (uint8_t*) realloc (mdata, desired);
if (data) {mdata = data;
mdatacapacity = desired;
else if (desired > mdatacapacity) {merror = no_memory;
return no_memory;
} else {if (Mdatasize > desired) {mdatasize = desired;
ALOGV ("Continuewrite Setting data size of%p to%d\n", this, mdatasize);
} if (Mdatapos > desired) {mdatapos = desired;
ALOGV ("Continuewrite Setting data pos of%p to%d\n", this, mdatapos); }} else {//is the.
easy!
uint8_t* data = (uint8_t*) malloc (desired);
if (!data) {merror = no_memory;
return no_memory; } if (! ( Mdatacapacity = = 0 && mobjects = NULL && mobjectscapacity = 0)) {aloge ("Continuewrite:%d/%p/%d/
%d ", mdatacapacity, Mobjects, mobjectscapacity, desired);
} mdata = data;
mdatasize = Mdatapos = 0;
ALOGV ("Continuewrite Setting data size of%p to%d\n", this, mdatasize); ALOGV ("ContinuewriTe Setting data pos of%p to%d\n ", this, mdatapos);
mdatacapacity = desired;
return no_error;
}
1. The entire reading and writing is in memory, mainly through malloc (), realloc (), memcpy () and other memory operations, so the efficiency than Java serialization in the use of external memory is much higher
2. When reading and writing is 4-byte aligned, you can see #define PAD_SIZE (((s) +3) &~3) The macro definition is doing this thing
3. If the unallocated space is not enough newsize = ((Mdatasize+len) *3)/2; it will be distributed more than once 50%
4. For ordinary data, the Mdata memory address is used, and the mobjects memory address is used for IBinder type of data and FileDescriptor. The latter is implemented through Flatten_binder () and Unflatten_binder (), and is designed to deserialize objects that are read as objects without having to recreate a new object.
6. Relevant examples
One last example.
The first is the serialized class Book.class
public class book implements parcelable{private String bookname;
Private String author;
private int publishdate;
Public book () {} public String Getbookname () {return bookname;
} public void Setbookname (String bookname) {this.bookname = BookName;
Public String Getauthor () {return author;
} public void Setauthor (String author) {this.author = author;
public int getpublishdate () {return publishdate;
The public void setpublishdate (int publishdate) {this.publishdate = publishdate;
@Override public int describecontents () {return 0;
@Override public void Writetoparcel (Parcel out, int flags) {out.writestring (bookname);
Out.writestring (author);
Out.writeint (publishdate); public static final parcelable.creator<book> Creator = new creator<book> () {@Override public Bo
Ok[] NewArray (int size) {return new book[size]; @Override Public book Createfromparcel (Parcel in) {return new book (in);
}
}; Public book (Parcel in) {//If the element data is a list type: Lits = new arraylist<?> in.readlist (list), or null pointer exception. And the data types read out and written must be
Must be the same. If you do not want to serialize some of the keywords, you can use the transient keyword to decorate and static adornments.
BookName = In.readstring ();
Author = in.readstring ();
Publishdate = In.readint ();
}
}
The first one activity,mainactivity
Book book = new book ();
Book.setbookname ("darker");
Book.setbookauthor ("Me");
Book.setpublishdate (a);
Bundle Bundle = new Bundle ();
Bundle.putparcelable ("book", book);
Intent Intent = new Intent (mainactivity.this,anotheractivity.class);
Intent.putextras (bundle);
A second activity,anotheractivity
Intent Intent = Getintent ();
Bundle bun = Intent.getextras ();
Book book = Bun.getparcelable ("book");
SYSTEM.OUT.PRINTLN (book);
Summary: There are serializable in the Java application to implement serialization operations, there are parcelable in Android to achieve serialization, and related performance comparisons are made. So in addition to the need to use serializable to serialize the data in Android, other times we still need to use parcelable for serialization, because efficiency is not the most important in Android, it's memory, By comparing Parcelable with serializable in both efficiency and memory, although parcelable is more complex to implement, if we want to be a good Android software engineer, Then we need to be diligent to achieve parcelable, rather than lazy and realize serializable. Of course, the latter is not impossible, the key lies in the mind of the idea.
The above is the entire content of this article, I hope to help you learn.