The long distance x--android serialization of Android development

Source: Internet
Author: User

This article is a series of articles, I am in the long-distance development of Android a little thoughts and records, I will try to follow the first easy after the difficult sequence to write the series. The series cited the "Android Development art exploration" and "in-depth understanding of Android volume Ⅰ,ⅱ,ⅲ" in the relevant knowledge, in addition to learn from other high-quality blog, here to the great God to thank you, worship!!! In addition, this article series of knowledge may require a certain Android Development Foundation and project experience to better understand, that is, the series of articles for Android Advanced Development engineer.

Objective

In the previous article, we analyzed the servicemanager in more detail. So let's take a look at the knowledge of Android serialization in this article. Why is the span so big because of "Caprice"? Not really, comrades remember the last two parcel that appeared, parcel is a container that can contain data or object references and can be used for the transfer of binders. It also supports serialization and deserialization after cross-process, while providing many ways to help developers with these functions. As can be seen from the above description, parcel is a data carrier for interprocess communication. We often need to persist some objects, in addition to persistence schemes such as databases, it is a good idea to convert objects into byte arrays and store them locally via streams, and when we need to transfer data through intent and binder, we need to use serialized data.

Serializable in Java

Serializable is a serialized interface provided by Java, an empty interface that provides standard serialization and deserialization operations for an object. Using serializable to serialize is fairly straightforward, so you can implement the default serialization process automatically by implementing the Serializable interface in a class that requires serialization and declaring an identity like the following in it.

public class person extends Personparent implements Serializable {private static final long serialversionuid = 1L;    static domain public static int static_field;    Transient domain public transient int transient_field;    A common domain public String desc;    Public person (String desc) {THIS.DESC = desc;        } Static class Personserializableproxy implements serializable{private String desc;        Private Personserializableproxy (person s) {this.desc = S.desc;         /** * is the same as Writereplace, ObjectInputStream calls the Readresolve () method through reflection, and determines whether to replace the deserialized object.        * @return */private Object readresolve () {return new person (DESC); }}/** * * When serializing an object, ObjectOutputStream calls the Writereplace method first by reflection, * Here we can replace the object that actually sent the sequence, * if we don't rewrite it,     The serialized object is the first object.         * @return */Private Object Writereplace () {//when serializing a person we did not write directly to the person object, but instead wrote the Personserializableproxy object return nEW Personserializableproxy (this);     }/** * Here is mainly to prevent attacks, any object declared by the person byte stream is rogue!! * Because I've pointed to the serialized instance in Writereplace serializableproxy * @param stream * @throws invalidobjectexception */privat  e void ReadObject (ObjectInputStream stream) throws invalidobjectexception {throw new Invalidobjectexception ("Proxy    Requied! ");} public static void Main (string[] args) throws IOException, classnotfoundexception {person person = new person ("des        C ");        Person.transient_field = 100;        Person.static_field = 10086;        ObjectOutputStream outputstream = new ObjectOutputStream (New FileOutputStream ("Cache.txt"));        Outputstream.writeobject (person);        Outputstream.flush ();        Outputstream.close ();        Person.static_field = 10087;        ObjectInputStream ObjectInputStream = new ObjectInputStream (New FileInputStream ("Cache.txt"));        Person deserialobj = (person) objectinputstream.readobject (); System.out.println (deserialobj);}}    Class personparent{private String name;    The Personparent class either inherits from the serializable or needs to provide a parameterless constructor.    Public personparent () {} public personparent (String name) {this.name = name; }}

However, there are several issues to be aware of in use:

    1. Serialversionuid is used to identify the class version of the current serialized object, and it is recommended that each class that implements serialization specify that domain. Of course, if we do not specify, the JVM will automatically generate a UID based on the information of the class.
    2. The static variables of the domain and class described by transient are not serialized, and serialization is for class instances.
    3. All domains that need to be serialized must implement the Serializable interface, or the error will be directly notserializableexception. Of course, there are two exceptions: the domain is empty or the domain is transient described without error.
    4. If an object that implements the serializable class inherits from another class, the class either inherits from Serializable or needs to provide a parameterless constructor.
    5. The objects produced by deserialization are not created by the constructor, so many constraints that depend on the constructor guarantee cannot be guaranteed when the object is deserialized. For example, a class designed to be a single case can be serialized to clone multiple instances in minutes ...
Parcelable in Android

Compared to serializable, the use of parcelable is more complex

  public class book implements parcelable {private String name;    Public book (String name) {this.name = name;    } protected Book (Parcel in) {name = In.readstring (); }//deserialization is done by Creator, which is indicated internally in Creator how to create sequence objects and arrays public static final creator<book> Creator = new creator< Book> () {//Deserialize object from Parcel @Override public book Createfromparcel (Parcel in) {//its internal call p        Arcel a series of readxxx methods to implement the deserialization process return new book (in);        }//Create serialized Array @Override public book[] NewArray (int size) {return new book[size];    }    };    @Override public int describecontents () {return 0; }//Serialization process://Override the Writetoparcel method, where we will write to the properties that need to be serialized in a series of writexxx methods of parcel, @Override public void Writetoparcel (Pa    Rcel dest, int flags) {dest.writestring (name); }}

As can be seen from the code comments above, it is cumbersome to write a class that implements the Parcelable interface, and we need to write each domain into the stream sequentially in Writetoparcel, as compared to serailable, In Createfromparcel we need to return a book object ourselves.

Parcelable is slightly different from serializable in use.

public class TestActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_test2);        //获取一个Parcel容器        Parcel parcel = Parcel.obtain();        //需要序列化的对象        Book book = new Book("c++");        //把对象写入Parcel        parcel.writeParcelable(book,0);        //Parcel读写共用一个位置计数,这里一定要重置一下当前的位置        parcel.setDataPosition(0);        //读取Parcel        Book book1 = parcel.readParcelable(Book.class.getClassLoader());        Log.d("TestActivity",book1.toString());    }}
Parcelable's Writing

Let's take a look at the Writeparcelable method
[Parcel.java]

public final void writeParcelable(Parcelable p, int parcelableFlags) {    //判断p是否为空    if (p == null) {        writeString(null);        return;    }    //① 先写入p的类名    writeParcelableCreator(p);    //② 调用我们重写的writeToParcel方法,按顺序写入域    p.writeToParcel(this, parcelableFlags);}public final void writeParcelableCreator(Parcelable p) {    //① 先写入p的类名    String name = p.getClass().getName();    writeString(name);}
Parcelable's Reading

Let's see the Readparcelable method.
[Parcel.java]

Public final <t extends parcelable> T readparcelable (ClassLoader loader) {//① call Readparcelablecreator//Then get on    Is our custom Creator parcelable.creator<?> Creator = readparcelablecreator (loader);    if (creator = = null) {return null; }//Determine if the current creator is parcelable.classloadercreator<?> instance if (creator instanceof Parcelable.classloadercreator&lt ;?      >) {//If yes, we call Reatefromparcel (this, loader);      Parcelable.classloadercreator<?> classloadercreator = (parcelable.classloadercreator<?>) creator;    Return (T) classloadercreator.createfromparcel (this, loader); }//Call our custom creator to override the Createfromparcel method in return (T) creator.createfromparcel (this);} Public final parcelable.creator<?> Readparcelablecreator (ClassLoader loader) {//first read out the class name String name = ReadS    Tring ();    Parcelable.creator<?> Creator; Mcreators did a bit of caching, if a previous classloader had taken a parcelable creator, then there was no need to find the synchronized by reflection (mCreators) {hashmap<string,parcelable.creator<?>> map = mcreators.get (loader);            if (map = = null) {map = new hashmap<> ();        Mcreators.put (loader, map);        } creator = Map.get (name); if (creator = = null) {try {ClassLoader Parcelableclassloader = (Loader = = null?                GetClass (). getClassLoader (): loader);                        Load our own class that implements the Parcelable interface class<?> parcelableclass = Class.forName (name, False,                                Parcelableclassloader);                Field f = Parcelableclass.getfield ("CREATOR");                class<?> Creatortype = F.gettype ();            Creator = (parcelable.creator<?>) f.get (null);                } catch (Exception e) {//catch Exception} if (creator = = null) {  throw new Badparcelableexception ("Parcelable protocol requires a"                      + "Non-null Parcelable.creator object called" + "Creator on class" + name);        } map.put (name, creator); }} return creator;}

Our test example reads parcel.

Book book1 = parcel.readParcelable(Book.class.getClassLoader());

You can see that we are using
Readparcelable, the passed parameter is the class loader of the book class, and according to our code above, we know that we will first get the Creator property defined in the book class by reflection, and we recall how the creator is defined in the book class.

    public static final Creator<Book> CREATOR = new Creator<Book>() {        //从Parcel中反序列化对象        @Override        public Book createFromParcel(Parcel in) {            //其内部调用Parcel的一系列readXXX方法实现反序列化过程            return new Book(in);        }        //创建序列化数组        @Override        public Book[] newArray(int size) {            return new Book[size];        }    };

After we get the Creator property, call its Createfromparcel method, which is called by polymorphism to the actual Createfromparcel method that we define in creator, Within this method we create the book object (the internal implementation is through a series of readxxx methods of parcel) and return. So now we have the deserialized object.

This article summarizes

We have analyzed the knowledge of Android serialization in detail, and you can use the serializable in Java or use parcelable.

The previous article in the next trailer is a summary of the previous article. Please look forward to the reader.

Sincerely, salute.

The long distance x--android serialization of Android development

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.