One, foreword

IPC is certainly familiar to Android developers, and it is a must to master IPC as an Android advancement. The so-called IPC mechanism is inter-process Communication. Sometimes, our application may be multi-process due to business needs. As different processes do not share a memory pool, they cannot communicate directly with each other, but need to communicate through some special mechanisms. Therefore, the IPC mechanism is a solution to inter-process communication. To get a feel for Android’s IPC mechanism, let’s start with basic serialization and deserialization.

Serialization and deserialization

At the bottom of the system, data transmission is in the form of simple byte sequence transmission, that is, at the bottom, the system does not know objects but only byte sequence. In order to achieve the purpose of process communication, data serialization is needed first, and serialization is the process of converting objects into byte sequence. Conversely, when the byte sequence is shipped to the corresponding process, the process, in order to recognize the data, deserializes it, that is, converting the byte sequence into an object. With that in mind, let’s look at two interfaces for serialization and deserialization: Serializable and Parcelable.

Serializable interface

Java provides a serialization interface, the Serialable interface, which is defined in the documentation as follows: Marks classes that can be serialized by ObjectOutputStream and deserialized by ObjectInputStream. ObjectOutputStream and ObjectInputStream do the serialization and deserialization of the current class. ObjectOutputStream and ObjectInputStream do the serialization and deserialization of the current class. Reading through the documentation, we find that the interface requires us to declare a variable in the class that implements the interface as follows:

private static final long serialVersionUID= 1L; 

Copy the code

What’s the use of this variable? If you didn’t specify this value manually, you first serialized classA, got file A, and then changed the internal structure of classA, such as adding A new variable, the deserialization would fail, because in fact the system would automatically calculate A serialVersionUID value at serialization time. If classA is changed, the system will recalculate a new serialVersionUID value during deserialization, and the two values will not be equal, and deserialization will fail. Therefore, manually specifying a value can save data to a large extent and prevent data loss. · object serialization: (1) instantiate an ObjectOutputStream: ObjectOutputStream, which can wrap an output stream, such as a file output stream. (2) using ObjectOutputStream. WriteObject write object (obj). · object deserialization: (1) instantiate an ObjectInputStream: ObjectInputStream, which can wrap an input stream, such as a file input stream. (2) use the ObjectInputStream. ReadObject read object (obj). The following is an example of how to implement serialization and deserialization:

package com.chenyu.serialable;  

import java.io.Serializable;  

public class User implements Serializable {  

    private static final long serialVersionUID = 1L;  

    public int id;  
    public String username;  
    public String email;  

    public User(int id, String username, String email) {  
        this.id = id;  
        this.username = username;  
        this.email = email; }}Copy the code

②Test tests whether serialization and deserialization are successful:

package com.chenyu.serialable;  

import java.io.FileInputStream;  
import java.io.FileNotFoundException;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.io.ObjectInputStream;  
import java.io.ObjectOutputStream;  

public class Test {  
    public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {  
        Instantiate the User class
        User user =new User(1."TestName"."[email protected]");  
        // Serialization process
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test.txt"));  
        objectOutputStream.writeObject(user);  
        objectOutputStream.close();  
        System.out.println("Serialization successful!");  
        // The deserialization process
        ObjectInputStream objectInputStream =new ObjectInputStream(new FileInputStream("test.txt"));  
        User newUser = (User) objectInputStream.readObject();  
        objectInputStream.close();  
        System.out.println("Deserialization successful!");  
        System.out.println("ID:"+newUser.id+" username:"+newUser.username+" Email:"+newUser.email); }}Copy the code

Run test.java and get the following result:

** Note: ** static member variables are classes, not objects, so they do not participate in serialization; Member variables marked with the TRANSIENT keyword do not participate in the serialization process.

4. Parcelable interface

Next up is the Parcelable interface, which is a new serialization method provided by Android. First, take a look at the official documentation for this interface: 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. In addition to implementing this interface method, you also need to create a static object called Creator. This object implements an anonymous inner class of Parcelable.Creator. The following is a typical example of a class that implements the Parcelable interface:

public class MyParcelable implements Parcelable {  
     private int mData;  

     public int describeContents(a) {  
         return 0;  
     }  

     public void writeToParcel(Parcel out, int flags) {  
         out.writeInt(mData);  
     }  

     public static final Parcelable.Creator<MyParcelable> CREATOR  
             = new Parcelable.Creator<MyParcelable>() {  
         public MyParcelable createFromParcel(Parcel in) {  
             return new MyParcelable(in);  
         }  

         public MyParcelable[] newArray(int size) {  
             return newMyParcelable[size]; }};private MyParcelable(Parcel in) { mData = in.readInt(); }}Copy the code

WriteToParcel (Parcel out,int flags) writes the current object to the serialization structure. ②createFromParcel(Parcel in): creates the original object from the serialized object ③newArray(int size): creates the original object array of the specified length ④MyParcelable(Parcel) WriteToParcel is responsible for serializing the object, while CREATOR is responsible for deserializing the data. As long as your class implements the Parcelable interface and implements the above methods, The object can then be serialized and deserialized automatically. WriteInt (data); writeInt(data); writeToParcel; writeInt(data);

out.writeInt(id);  
out.writeString(name);  
out.writeString(email); 

Copy the code

After doing so, the corresponding MyParcelable(Parcel in) deserialization method must also read:

in.readInt();  
in.readString();  
in.readString(); 

Copy the code

That is, the order should correspond one to one, otherwise, the data extracted will be wrong.

So far, Serialable interface and Parcelable interface have been introduced, which are basic concepts in IPC mechanism and should be mastered. Because the level is limited, have wrong place unavoidable, rather misdirect others, welcome big guy to point out! Code word is not easy, thank you for your attention!

🙏 If you are studying with me, you can follow my official account — ❤️ Program ape Development Center ❤️. Every week, we will share the technology of Android regularly.