Analysis and use of parcel in Android

Source: Internet
Author: User

To put it simply, parcel is a container for storing and reading data. In the Android system, the binder Process Communication (IPC) uses the parcel class to exchange data between the client and the server, in addition, aidl data is also interactive through parcel. Both Java space and C ++ implement parcel. Because it directly uses memory to read data in C/C ++, it is more efficient.

Analyze the actual ontransact () function of the client and server in the binder mechanism:

    1. // Parameter description:
    2. // Code: the ID of the request
    3. // Data: parameters sent by the client request
    4. // Reply: The result returned by the server
    5. // Flags: some additional identifiers, such as flag_oneway, usually 0.
    6. Virtual status_t ontransact (uint32_t code,
    7. Const parcel & data,
    8. Parcel * reply,
    9. Uint32_t flags = 0 );

CopyCode

We can see the importance of parcel and its usage. Next, I will mainly analyze its storage mechanism.

 

Common Methods:

Obtain () gets a new parcel, which is equivalent to a new object.

Datasize () to get the actual storage space of the current parcel object

Datacapacity () to get the allocated storage space of the current parcel object,> = datasize () value (Change Time by space)

Datapostion () gets the offset of the current parcel object (similar to the offset of the file stream pointer)

Setdataposition () sets the offset

Recyle () clears and recycles the memory of the parcel object

Writeint (INT) writes an integer

Writefloat (float) writes a floating point number

Writedouble (double) Write a double number

Writestring (string) Write a string

Of course, there are more writexxx () methods, which correspond to readxxx (). For details, see the SDK.

Several noteworthy methods are as follows:

Writeexception () writes an exception in the parcel header.

Writeexception () write "no exception" to the parcel Header

Readexception () is read in the parcel header. If the read value is abnormal, this exception is thrown. Otherwise,ProgramNormal operation.

1. Analysis of parcel

I believe that I have read the previous values and have a preliminary impression on the use of parcel. So what is the internal storage mechanism of parcel? The offset is

What is the situation? Let's recall the value range of the basic data type:

Boolean 1bit 1 byte

Char 16bit 2 bytes

Int 32bit 4 bytes

Long 64bit 8 bytes

Float 32bit 4 bytes

Double 64bit 8 bytes

 

If you are familiar with the C language, the memory alignment of the structure in the C language is the same as the memory storage mechanism used by parcel, that is, read the minimum byte.

32 bits, that is, 4 bytes. If the value is greater than 4 bytes, it is stored as the actual data type, but must be a multiple of 4 bytes. The basic formula is as follows:

Actual storage Bytes:

Discriminant 1: 32bit (<= 32bit) for example: Boolean, Char, int

Discriminant 2: The actual bytes used (> 32 bit), such as long, float, string, and array.

When we use the readxxx () method, the read method is also as described above:

Actually read Bytes:

Discriminant 1: 32bit (<= 32bit) for example: Boolean, Char, int

Criterion 2: The actual byte size (> 32 bit), for example, long, float, string, and numeric.

As you can see, when we write/read a data, the offset must be at least 4 bytes (32bit). Therefore, the offset formula is as follows:

F (x) = 4x (x = 0, 1 ,... N)

In fact, we can use setdatapostion (INT postion) to directly manipulate the offset when we want to read data. Undoubtedly,

You can set any offset, but the read value may be of a type error. Therefore, be careful when setting the offset read value.

 

Another note is that the offset caused by writexxx () and readxxx () is shared. For example, after writeint (23,

At this time, datapostion = 4. If we want to read 5, it is not possible to simply use readint (), and we can only get 0. In this case, we can only

Setdataposition (0) is set to the starting offset, and four bytes are read from the starting position, that is, 23. Therefore, when reading a value, you may need to use

Setdatapostion (INT postion) changes the offset to our value.

 

The setdataposition () method is used to quickly read data of only a certain type in our parcel object.

All values. The specific method is as follows:

 

  1. View plainprint?
  2. /**
  3. * Prerequisites: parcel has multiple objects of the same type. In this example, we describe 10 float objects:
  4. */
  5. Public void readsametype (){
  6. Parcel parcel = parcel. Obtain ();
  7. For (INT I = 0; I <10; I ++ ){
  8. Parcel. writedouble (I );
  9. Log. I (TAG, "Write double ---->" + getparcelinfo ());
  10. }
  11. // Method 1: display the Set offset
  12. Int I = 0;
  13. Int datasize = parcel. datasize ();
  14. While (I <datasize ){
  15. Parcel. setdataposition (I );
  16. Double fvalue = parcel. readdouble ();
  17. Log. I (TAG, "Read double is =" + fvalue + ", --->" + getparcelinfo ());
  18. I + = 8; // double occupies 8 bytes
  19. }
  20. // Method 2. Because the object type is consistent, we can directly use readxxx () to read the value and produce an offset.
  21. // Parcel. setdataposition (0 );//
  22. // While (parcel. dataposition () <parcel. datasize ()){
  23. // Double fvalue = parcel. readdouble ();
  24. // Log. I (TAG, "Read double is =" + fvalue + ", --->" + getparcelinfo ());
  25. //}
  26. }

Copy code

Due to the possible deviation of the read value, a default value can be:

1. When reading a complex object: when the object matches, the object at the current offset is returned;

If the object does not match, null is returned;

2. When reading a simple object: when the object matches, the object at the current offset is returned;

If the object does not match, 0 is returned;

Next, we will provide a simple storage space map for parcel. We hope you can better understand it while understanding it. It's a little simple. Please forgive me.

 

 

I believe that through the previous introduction, you will be very familiar with the storage mechanism of parcel. The following is an application for practice.

1. The layout file is as follows:

  1. <Span> <? XML version = "1.0" encoding = "UTF-8"?>
  2. <Linearlayout xmlns: Android = "http://schemas.android.com/apk/res/android"
  3. Android: Orientation = "vertical" Android: layout_width = "fill_parent"
  4. Android: layout_height = "fill_parent">
  5. <Textview Android: layout_width = "fill_parent"
  6. Android: layout_height = "wrap_content" Android: text = "@ string/Hello"/>
  7. <Linearlayout Android: Orientation = "horizontal"
  8. Android: layout_width = "fill_parent" Android: layout_height = "wrap_content">
  9. <Button Android: Id = "@ + ID/btwritebyte" Android: layout_width = "wrap_content"
  10. Android: layout_height = "wrap_content" Android: text = "Write a byte value"> </button>
  11. <Button Android: Id = "@ + ID/btwriteint" Android: layout_width = "wrap_content"
  12. Android: layout_height = "wrap_content" Android: text = "write an int value"> </button>
  13. </Linearlayout>
  14. <Linearlayout Android: Orientation = "horizontal"
  15. Android: layout_width = "fill_parent" Android: layout_height = "wrap_content">
  16. <Button Android: Id = "@ + ID/btwritedouble" Android: layout_width = "wrap_content"
  17. Android: layout_height = "wrap_content" Android: text = "Write a double value"> </button>
  18. <Button Android: Id = "@ + ID/btwritestring" Android: layout_width = "wrap_content"
  19. Android: layout_height = "wrap_content" Android: text = "Write a string value"> </button>
  20. </Linearlayout>
  21. <View Android: layout_width = "fill_parent" Android: layout_height = "2dip"
  22. Android: Background = "# ff1493"> </View>
  23. <Linearlayout Android: Orientation = "horizontal"
  24. Android: layout_margintop = "5dip" Android: layout_width = "fill_parent"
  25. Android: layout_height = "wrap_content">
  26. <Button Android: Id = "@ + ID/btreadbyte" Android: layout_width = "wrap_content"
  27. Android: layout_height = "wrap_content" Android: text = "read a byte value"> </button>
  28. <Button Android: Id = "@ + ID/btreadint" Android: layout_width = "wrap_content"
  29. Android: layout_height = "wrap_content" Android: text = "read an int value"> </button>
  30. </Linearlayout>
  31. <Linearlayout Android: Orientation = "horizontal"
  32. Android: layout_width = "fill_parent" Android: layout_height = "wrap_content">
  33. <Button Android: Id = "@ + ID/btreaddouble" Android: layout_width = "wrap_content"
  34. Android: layout_height = "wrap_content" Android: text = "read a double value"> </button>
  35. <Button Android: Id = "@ + ID/btreadstring" Android: layout_width = "wrap_content"
  36. Android: layout_height = "wrap_content" Android: text = "read a string value"> </button>
  37. </Linearlayout>
  38. <View Android: layout_width = "fill_parent" Android: layout_height = "2dip"
  39. Android: Background = "# ff1493"> </View>
  40. <Button Android: Id = "@ + ID/btsametype" Android: layout_width = "wrap_content"
  41. Android: layout_height = "wrap_content" Android: text = "use setdataposition to read multiple values"> </button>
  42. </Linearlayout>

Copy code

2. The configuration file is as follows:

  1. <? XML version = "1.0" encoding = "UTF-8"?>
  2. <Manifest xmlns: Android = "http://schemas.android.com/apk/res/android"
  3. Package = "com. qinjuning. parcel"
  4. Android: versioncode = "1"
  5. Android: versionname = "1.0" type = "codeph" text = "/codeph">
  6. <Application Android: icon = "@ drawable/icon" Android: Label = "@ string/app_name">
  7. <Activity Android: Name = ". mainactivity" Android: Label = "@ string/app_name">
  8. <Intent-filter>
  9. <Action Android: Name = "android. Intent. Action. Main"/>
  10. <Category Android: Name = "android. Intent. Category. launcher"/>
  11. </Intent-filter>
  12. </Activity>
  13. </Application>
  14. </Manifest>

Copy code

3. The main program file is as follows:

  1. <Span> public class mainactivity extends activity implements onclicklistener {
  2. Private Static string tag = "parceltest ";
  3. // Button ID
  4. Private Static int [] btids = new int [] {R. Id. btwritebyte, R. Id. btwriteint,
  5. R. Id. btreaddouble, R. Id. btwritestring, R. Id. btreadbyte,
  6. R. Id. btreadint, R. Id. btreaddouble, R. Id. btreadstring,
  7. R. Id. btsametype };
  8. // The current value of each type
  9. Private byte cur_byte = 1; // false for each write
  10. Private int cur_int = 10; // write value cur_int ++;
  11. Private double cur_float = 100w.d; // write value cur_float ++;
  12. Private string cur_str = "qinjun -->" + cur_int; // write value "qinjun -->" + cur_int
  13. Private parcel = NULL;
  14. @ Override
  15. Public void oncreate (bundle savedinstancestate ){
  16. Super. oncreate (savedinstancestate );
  17. Setcontentview (R. layout. Main );
  18. For (INT I = 0; I <btids. length; I ++ ){
  19. Button bt = (button) findviewbyid (btids [I]);
  20. Bt. setonclicklistener (this );
  21. }
  22. Parcel = parcel. Obtain (); // obtain a parcel object, which is equivalent to a new object and the initial size is 0.
  23. Log. I (TAG, "the original parcel Info" + getparcelinfo ());
  24. }
  25. @ Override
  26. Public void onclick (view ){
  27. // Todo auto-generated method stub
  28. Int viewviewid = view. GETID ();
  29. Switch (viewid ){
  30. Case R. Id. btwritebyte:
  31. Parcel. setdataposition (0 );
  32. Parcel. writebyte (cur_byte );
  33. Log. I (TAG, "After Write byte, --->" + getparcelinfo ());
  34. Break;
  35. Case R. Id. btwriteint:
  36. Parcel. writeint (cur_int );
  37. Log. I (TAG, "After Write int, --->" + getparcelinfo ());
  38. Break;
  39. Case R. Id. btwritedouble:
  40. Parcel. writedouble (cur_float );
  41. Log. I (TAG, "After Write float, --->" + getparcelinfo ());
  42. Break;
  43. Case R. Id. btwritestring:
  44. Parcel. writestring (cur_str );
  45. Log. I (TAG, "After Write string, --->" + getparcelinfo ());
  46. Break;
  47. Case R. Id. btreadbyte:
  48. Byte B = parcel. readbyte ();
  49. Log. I (TAG, "Read byte is =" + B + ", --->" + getparcelinfo ()
  50. + "String ");
  51. Break;
  52. Case R. Id. btreadint:
  53. Int I = parcel. readint ();
  54. Log. I (TAG, "Read Int Is =" + I + ", --->" + getparcelinfo ());
  55. Break;
  56. Case R. Id. btreaddouble:
  57. Float F = parcel. readfloat ();
  58. Readsametype ();
  59. Log. I (TAG, "Read float is =" + F + ", --->" + getparcelinfo ());
  60. Break;
  61. Case R. Id. btreadstring:
  62. Parcel. setdataposition (0 );
  63. String STR = parcel. readstring ();
  64. Log. I (TAG, "Read float is =" + STR + ", --->" + getparcelinfo ());
  65. Break;
  66. Case R. Id. btsametype:
  67. Readsametype ();
  68. Break;
  69. Default:
  70. Break;
  71. }
  72. }
  73. Private string getparcelinfo () {// get the parcel information
  74. Return "datasize =" + parcel. datasize () + ", datacapacity ="
  75. + Parcel. datacapacity () + ", datapositon ="
  76. + Parcel. dataposition ();
  77. }
  78. /**
  79. * Prerequisites: parcel has multiple objects of the same type. In this example, we describe 10 float objects:
  80. */
  81. Public void readsametype (){
  82. For (INT I = 0; I <10; I ++ ){
  83. Parcel. writedouble (I );
  84. Log. I (TAG, "Write double ---->" + getparcelinfo ());
  85. }
  86. // Method 1: display the Set offset
  87. Int I = 0;
  88. Int datasize = parcel. datasize ();
  89. While (I <datasize ){
  90. Parcel. setdataposition (I );
  91. Double fvalue = parcel. readdouble ();
  92. Log. I (TAG, "Read double is =" + fvalue + ", --->" + getparcelinfo ());
  93. I + = 8; // double occupies 8 bytes
  94. }
  95. // Method 2. Because the object type is consistent, we can directly use readxxx () to read the value and produce an offset.
  96. // Parcel. setdataposition (0 );//
  97. // While (parcel. dataposition () <parcel. datasize ()){
  98. // Double fvalue = parcel. readdouble ();
  99. // Log. I (TAG, "Read double is =" + fvalue + ", --->" + getparcelinfo ());
  100. //}
  101. }
  102. }

Copy code

Because there may be type conversion during the value, the expected results may not be generated when you click the button. Therefore, the correctness of the offset value must be ensured.

 

Reprinted from: http://www.eoeandroid.com/blog-129327-2029.html

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.