Serialized storage of objects: Serializable and Parceable

Serialized storage of objects: Serializable and Parceable

When developing Android, we sometimes need to use persistent storage of data or transfer data between processes. This may require object serialization, which can be transmitted through Intent or Boundle. Let's introduce it in detail.

1. What is serialization and what is deserialization

Serialization: The process of converting a data structure or object into a binary string. Deserialization: The process of converting the binary string generated during the serialization process into a data structure or object.

In simple terms, serialization is to store the objects we generate (such as on disk) for future use or transmission on the network, while deserialization is the process of regenerating objects from the binary strings generated by our previous serialization. Note that the serialization and deserialization we repeatedly mention here are all for objects, not classes. Because we access and transmit objects, not classes, when we need to retrieve the previous object, we read it directly (from a file or network), rather than creating a new object based on the class. This is something that needs to be noted.

2. How to serialize

There are two ways to serialize, one is to implement the Serializable interface, the other is to implement the Parceable interface, these two methods will be described in detail below.

a. Implement the Serializable interface

This serialization method is provided by Java. Its advantage is simplicity. In fact, the Serializable interface is an empty interface, so we do not need to implement any abstract methods. However, we often need to declare a static variable identifier (serialVersionUID) in the class, but this is not necessary. We can still implement serialization without declaring it, but this will have a certain impact on deserialization, and may cause the deserialization of the object to fail after we modify the class. The declaration method is as follows:

  1. private static final long serialVersionUID = 8711368828010083044L;

Note that the value here can be anything.

Let's implement it in detail below.

  1. package com.qc.admin.myserializableparceabledemo;
  2.  
  3. import java.io.Serializable ;
  4.  
  5. /**
  6. * Created by admin on 2016/12/1.
  7. */
  8.  
  9. public class User implements Serializable {
  10.  
  11. private static final long serialVersionUID = 519067123721295773L;
  12.  
  13. public   int userId;
  14. public String userName;
  15. public boolean isMale;
  16.  
  17. public   User ( int userId, String userName, boolean isMale) {
  18.  
  19. this.userId = userId;
  20. this.userName = userName;
  21. this.isMale = isMale;
  22.  
  23. }
  24.  
  25. @Override
  26. public String toString() {
  27. return   "User{ " +
  28. "userId = " + userId +
  29. ", userName = " + userName +
  30. ", isMale = " + isMale +
  31. " }" ;
  32. }
  33. }

The following is the serialization and deserialization process:

  1. private void beginSerizable() throws IOException, ClassNotFoundException {
  2.  
  3. //Serialization
  4. User   user = new User (2016, "qian" , true );
  5. ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(new File(getFilesDir(), "myfile.txt" )));
  6. out .writeObject( user );
  7. out . close ();
  8.  
  9. // Deserialization
  10. // Note that there is a slash "/" before the "/myfile.txt" here, otherwise a "FileNotFoundException" will be reported
  11. ObjectInputStream in = new ObjectInputStream(new FileInputStream(getFilesDir() + "/myfile.txt" ));
  12. User mUser = ( User ) in .readObject();
  13. textView.setText(mUser.toString());
  14. in .close () ;
  15. Log.i( "test" ,mUser.toString());
  16. }

Screenshot of the operation results:

Note: If you call the above method in an Android project, don't forget to configure the following permissions in the Manifest.xml file:

  1. <uses-permission android: name = "android.permission.READ_EXTERNAL_STORAGE" />
  2. <uses-permission android: name = "android.permission.WRITE_EXTERNAL_STORAGE" />

b. Implement the Parceable interface

This method is provided by Android. Compared with the previous method, this method is a little more complicated. We need to perform serialization and deserialization operations by ourselves, but it is more efficient and does not require a large number of I/O operations. And this method is also the serialization method recommended by Android, so we should use Parceable. As long as this interface is implemented, objects of a class can be serialized and passed through Intent and Binder. Please see the example below:

  1. public class Book implements Parcelable {
  2. public String bookTitle;
  3. public   int bookId;
  4.  
  5. protected Book(Parcel in ) {
  6. bookTitle = in .readString();
  7. bookId = in .readInt();
  8. }
  9.  
  10. public   static final Creator<Book> CREATOR = new Creator<Book>() {
  11. @Override
  12. public Book createFromParcel(Parcel in ) {
  13. return new Book( in );
  14. }
  15.  
  16. @Override
  17. public Book[] newArray( int   size ) {
  18. return new Book[ size ];
  19. }
  20. };
  21.  
  22. @Override
  23. public   int describeContents() {
  24. return 0;
  25. }
  26.  
  27. @Override
  28. public void writeToParcel(Parcel parcel, int i) {
  29. parcel.writeString(bookTitle);
  30. parcel.writeInt(bookId);
  31. }
  32. }

Here, the Book class implements the Parcelable interface. In fact, in Android Studio IDE, the above process is very simple. We only need to define a class, implement the Parcelable interface, and then define our attributes or fields in it. According to the prompt error, overwrite the corresponding method according to the prompt method. Everything after that can actually be automatically generated (but if you need to construct a method, you need to generate it automatically, and the toString() method is also implemented by yourself), so don’t worry about it being troublesome to implement the Parceable interface in Android development, because AS will automatically generate it for you. Above, we have completely implemented the Parceable interface for the Book class, so how to serialize and deserialize it next? If you say, didn’t I just say that it will be possible to use file reading... When you do that, you will find that the following error will be reported:

Why???...What's going on? It reminds us that the Book class is not serialized:

  1. /System.err: java.io.NotSerializableException: com.qc.admin.myserializableparceabledemo.Book

Well, the reason for this problem is not that there is a problem with our implementation process, but that the way of using this class does not work. At this point, we understand that there is a difference between Serializable and Parceable in implementing serialization. As we said just now, Parceable is more efficient and does not have a large number of I/O operations like Serializable. The specific meaning of this sentence reveals the difference between Serializable and Parcelable: Although both are used to support serialization and deserialization operations, the biggest difference between the two lies in the different storage media. Serializable stores serialized objects on the hard disk and uses I/O reading and writing, while Parcelable stores them in memory and reads and writes memory. Friends who are familiar with the principles of computer composition know that the reading and writing speed of memory is obviously much faster than the reading and writing speed of I/O. This is why Android recommends using Parcelable to implement object serialization.

So how should we use objects that are serialized by implementing the Parcelable interface? The answer is: through the Intent method. In addition to basic types, Intent can only transmit serialized objects. Corresponding to these two serialization methods, there are also two corresponding methods:

  1. mIntent.getSerializableExtra(string name );
  1. mIntent.getParcelableExtra(String name );

Of course, there is no such distinction for insert operations, they are all methods:

  1. mIntent.putExtra();

We can put the serialized object into the Intent in the first Activity and take it out in another Activity, for example: Get the object at the other end, for example:

  1. Bundle mBundle = getIntent().getExtras();
  2. Book mBook = mBundle.getParcelable( "book1" );

Next, let's look at the process of implementing the Parceable interface in the User class. It contains a serializable class Book. The specific details are slightly different from the above:

  1. package com.qc.admin.myserializableparceabledemo;
  2.  
  3. import android.os.Parcel;
  4. import android.os.Parcelable;
  5.  
  6. /**
  7. * Created by admin on 2016/12/1.
  8. */
  9.  
  10. public class User implements Parcelable {
  11.  
  12. public   int userId;
  13. public String userName;
  14. public boolean isMale;
  15. public Book book;
  16.  
  17.  
  18. public   User ( int userId, String userName, boolean isMale, Book book) {
  19.  
  20. this.userId = userId;
  21. this.userName = userName;
  22. this.isMale = isMale;
  23. this.book = book;
  24. }
  25.  
  26.  
  27. protected User (Parcel in ) {
  28. userId = in .readInt();
  29. userName = in .readString();
  30. isMale = in .readByte() != 0;
  31. // This is the difference 1
  32. // You can also use this method: book = in .readParcelable(Thread.currentThread().getContextClassLoader());
  33. book = in .readParcelable(Book.class.getClassLoader());
  34.          
  35. }
  36.  
  37. public   static final Creator< User > CREATOR = new Creator< User >() {
  38. @Override
  39. public   User createFromParcel(Parcel in ) {
  40. return new User ( in );
  41. }
  42.  
  43. @Override
  44. public   User [] newArray( int   size ) {
  45. return new User [ size ];
  46. }
  47. };
  48.  
  49.  
  50. // Should return 0 in almost all cases. This method returns CONTENTS_FILE_DESCRIPTOR (constant value 1) only when there is a file description in the current object
  51. @Override
  52. public   int describeContents() {
  53. return 0;
  54. }
  55.  
  56. // Write the object to the serialized structure, where the i flag has two values, 0 or 1 (PARCELABLE_WRITE_RETURN_VALUE)
  57. // When it is 1, it means that the current object needs to be returned as the return value and the resources cannot be released immediately. In almost all cases, it is 0
  58. @Override
  59. public void writeToParcel(Parcel parcel, int i) {
  60. parcel.writeInt(userId);
  61. parcel.writeString(userName);
  62. // Note that here, we are not writing a boolean value directly, but an integer value
  63. parcel.writeByte((byte) (isMale ? 1 : 0));
  64. // This is the difference 2
  65. parcel.writeParcelable(book, i);
  66. }
  67.  
  68. @Override
  69. public String toString() {
  70. return   "User{ " +
  71. "userId = " + userId +
  72. ", userName = " + userName +
  73. ", isMale = " + isMale +
  74. "book = " + book.toString() +
  75. " }" ;
  76. }
  77.  
  78. }

As you can see, the result has been printed correctly:

Note: In Parcelable, we cannot write boolean values ​​directly, but convert them into integer values ​​for storage, here is Byte, of course, you can also use Int, etc.

<<:  Implementing a long connection between Android and the server based on a custom protocol based on Java Socket (Part 2)

>>:  Rexxar: Douban's thoughts on hybrid development

Recommend

A piece of ginkgo leaf you picked up may come from billions of years ago

As the temperature gradually drops, the ginkgo be...

What is the promotion method of Xiaohongshu? How to promote Xiaohongshu?

In fact, most of the Xiaohongshu merchants are mo...

Baidu Netdisk Super 0 Tutorial Course Materials

Baidu Netdisk Super 0 Tutorial Course Materials 1...

How does the gaming industry advertise on Weibo?

How to correctly direct traffic during the promot...

What are the requirements for registering a limited partnership?

1. Conditions for registering a partnership 1. Th...

What types of ads should you pay attention to when promoting Baidu Union?

Baidu Union Promotion is one of the core products...

What skills do event planners need to have to get a high salary?

What is the core competitiveness of event plannin...

Practical! Keep this guide to avoid scams during the May Day holiday

Have you ever encountered the traps of holiday tr...

Deepin launches Deepal AD+ Deepal OS

On November 6, DeepBlue Automotive's intellig...

How to create a travel-related TikTok account from 0 to 1?

1. Industry Background As we all know, Douyin is ...