日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Android中的序列化機制

 jiffes 2019-02-12

當我們在調(diào)用遠程方法時,需要在進程間傳遞參數(shù)以及返回結(jié)果。這種類似的處理方式,需要把數(shù)據(jù)與進程相關(guān)性去除,變成一種中間形式,然后按統(tǒng)一的接口進行讀寫操作。這樣的機制,一般在高級編程語言里都被稱為序列化。


在Android世界里處理數(shù)據(jù)的序列化操作的,使用了一種Parcel類,而能夠處理數(shù)據(jù)序列能力,則是實現(xiàn)Parcelable接口來實現(xiàn)。于是,當我們需要在進程間傳輸一個對象,則實現(xiàn)這一對象的類必須實現(xiàn)Parcelable接口里定義的相應(yīng)屬性或方法,而在使用這一對象時,則可以使用一個Parcel引用來處理傳輸時的基本操作。


ParcelSerialize很類似,只是它是在內(nèi)存中完成的序列化和反序列化,利用的是連續(xù)的內(nèi)存空間,因此會更加高效。


1. Parcelable接口

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。


2.實現(xiàn)Parcelable就是為了進行序列化,那么,為什么要序列化?
1)永久性保存對象,保存對象的字節(jié)序列到本地文件中;
2)通過序列化對象在網(wǎng)絡(luò)中傳遞對象;
3)通過序列化在進程間傳遞對象。


3.實現(xiàn)序列化的方法
Android中實現(xiàn)序列化有兩個選擇:一是實現(xiàn)Serializable接口(是JavaSE本身就支持的),一是實現(xiàn)Parcelable接口(是Android特有功能,效率比實現(xiàn)Serializable接口高效,可用于Intent數(shù)據(jù)傳遞,也可以用于進程間通信(IPC))。實現(xiàn)Serializable接口非常簡單,聲明一下就可以了,而實現(xiàn)Parcelable接口稍微復(fù)雜一些,但效率更高,推薦用這種方法提高性能。
注:Android中Intent傳遞對象有兩種方法:一是Bundle.putSerializable(Key,Object),另一種是Bundle.putParcelable(Key,Object)。當然這些Object是有一定的條件的,前者是實現(xiàn)了Serializable接口,而后者是實現(xiàn)了Parcelable接口。


4.選擇序列化方法的原則
1)在使用內(nèi)存的時候,Parcelable比Serializable性能高,所以推薦使用Parcelable。
2)Serializable在序列化的時候會產(chǎn)生大量的臨時變量,從而引起頻繁的GC。
3)Parcelable不能使用在要將數(shù)據(jù)存儲在磁盤上的情況,因為Parcelable不能很好的保證數(shù)據(jù)的持續(xù)性在外界有變化的情況下。盡管Serializable效率低點,但此時還是建議使用Serializable 。


5.應(yīng)用場景

需要在多個部件(Activity或Service)之間通過Intent傳遞一些數(shù)據(jù),簡單類型(如:數(shù)字、字符串)的可以直接放入Intent。復(fù)雜類型必須實現(xiàn)Parcelable接口。


6.Serializable實現(xiàn)與Parcelabel實現(xiàn)的區(qū)別
1)Serializable的實現(xiàn),只需要implements  Serializable 即可。這只是給對象打了一個標記,系統(tǒng)會自動將其序列化。
2)Parcelabel的實現(xiàn),不僅需要implements  Parcelabel,還需要在類中添加一個靜態(tài)成員變量CREATOR,這個變量需要實現(xiàn) Parcelable.Creator 接口。

1)創(chuàng)建Person類,實現(xiàn)Serializable:

  1. public class Person implements Serializable
  2. {
  3. private static final long serialVersionUID = -7060210544600464481L;
  4. private String name;
  5. private int age;
  6. public String getName()
  7. {
  8. return name;
  9. }
  10. public void setName(String name)
  11. {
  12. this.name = name;
  13. }
  14. public int getAge()
  15. {
  16. return age;
  17. }
  18. public void setAge(int age)
  19. {
  20. this.age = age;
  21. }
  22. }

2)創(chuàng)建Book類,實現(xiàn)Parcelable:

  1. public class Book implements Parcelable
  2. {
  3. private String bookName;
  4. private String author;
  5. private int publishDate;
  6. public Book()
  7. {
  8. }
  9. public String getBookName()
  10. {
  11. return bookName;
  12. }
  13. public void setBookName(String bookName)
  14. {
  15. this.bookName = bookName;
  16. }
  17. public String getAuthor()
  18. {
  19. return author;
  20. }
  21. public void setAuthor(String author)
  22. {
  23. this.author = author;
  24. }
  25. public int getPublishDate()
  26. {
  27. return publishDate;
  28. }
  29. public void setPublishDate(int publishDate)
  30. {
  31. this.publishDate = publishDate;
  32. }
  33. @Override
  34. public int describeContents()
  35. {
  36. return 0;
  37. }
  38. @Override
  39. public void writeToParcel(Parcel out, int flags)
  40. {
  41. out.writeString(bookName);
  42. out.writeString(author);
  43. out.writeInt(publishDate);
  44. }
  45. public static final Parcelable.Creator<Book> CREATOR = new Creator<Book>()
  46. {
  47. @Override
  48. public Book[] newArray(int size)
  49. {
  50. return new Book[size];
  51. }
  52. @Override
  53. public Book createFromParcel(Parcel in)
  54. {
  55. return new Book(in);
  56. }
  57. };
  58. public Book(Parcel in)
  59. {
  60. bookName = in.readString();
  61. author = in.readString();
  62. publishDate = in.readInt();
  63. }
  64. }


1、describeContents(),Parcelabl所需要的接口方法之一,必須實現(xiàn)。這一方法作用很簡單,就是通過返回的整形來描述這一Parcel是起什么作用的,通過這一整形每個bit來描述其類型,一般會返回0。
2、writeToParcel(),Parcelabl所需要的接口方法之二,必須實現(xiàn)。writeToParcel()方法的作用是發(fā)送,就是將類所需要傳輸?shù)膶傩詫懙絇arcel里,被用來提供發(fā)送功能的Parcel,會作為第一個參數(shù)傳入,于是在這個方法里都是使用writeInt()、writeLong()寫入到Parcel里。這一方法的第二參數(shù)是一個flag值,可以用來指定這樣的發(fā)送是單向還是雙向的,可以與aidl的in、out、inout三種限定符匹配。
3、CREATOR對象,Parcelable接口所需要的第三項,必須提供實現(xiàn),但這是一個是接口對象。正如我們看到的,這一CREATOR對象,是使用模板類Parcelable.Creator,套用到TaskInfo來得到的,Parcelable.Creator<TaskInfo>。這個CREATOR對象在很大程度上是一個工廠(Factory)類,用于遠程對象在接收端的創(chuàng)建。從某種意義上來說,writeToParcel()與CREATOR是一一對應(yīng)的,發(fā)送端進程通過writeToParcel(),使用一個Parcel對象將中間結(jié)果保存起來,而接收端進程則會使用CREATOR對象把作為Parcel對象的中間對象再恢復(fù)出來,通過類的初始化方法以這個Parcel對象為基礎(chǔ)來創(chuàng)建新對象。后續(xù)的4-6,則是完成這個CREATOR對象的實現(xiàn)。
4、createFromParcel(),這是ParcelableCreator<T>模板類所必須實現(xiàn)的接口方法,提供從Parcel轉(zhuǎn)義出新的對象的能力。接收端來接收傳輸過來的Parcel對象時,便會以這一個接口方法來取得對象。我們這里直接調(diào)用基于Parcel 的類的初始化方法,然后將創(chuàng)建的對象返回。
5、newArray(),這是ParcelableCreator<T>模板類所必須實現(xiàn)的另一個接口方法,但這一方法用于創(chuàng)建多個這種實現(xiàn)了Parcelable接口的類。通過這一方法,CREATOR對象不光能創(chuàng)建單個對象,也能返回多個創(chuàng)建好的空對象,但多個對象不能以某個Parcel對象為基礎(chǔ)創(chuàng)建,于是會使用默認的類創(chuàng)始化方法。
6、實現(xiàn)具體的以Parcel為參照的初始化方法,這并非必須,我們也可以在createFromParcel()里直接根據(jù)Parcel的值賦值到對象來實現(xiàn),但這樣實現(xiàn)則更清晰。這一方法,基本上與writeToParcel()是成對的,以什么順序?qū)ο髮傩詫懭隤arcel,則在createFromParcel()會就會以同樣的順序?qū)ο髮傩詮腜arcel里讀出來,使用Parcel的readInt()、readLong()等方法來完成。


7.應(yīng)用實例

就應(yīng)用程序而言,最常見使用Parcel類的場景就是在Activity間傳遞數(shù)據(jù)。沒錯,在Activity間使用Intent傳遞數(shù)據(jù)的時候,可以通過Parcelable機制傳遞復(fù)雜的對象。

 在下面的程序中,MyColor用于保存一個顏色值,MainActivity在用戶點擊屏幕時將MyColor對象設(shè)成紅色,傳遞到SubActivity中,此時SubActivity的TextView顯示為紅色的背景;當點擊SubActivity時,將顏色值改為綠色,返回MainActivity,期望的是MainActivity的TextView顯示綠色背景。
MyColor類的實現(xiàn)代碼:

  1. package com.test;
  2. import android.graphics.Color;
  3. import android.os.Parcel;
  4. import android.os.Parcelable;
  5. public class MyColor implements Parcelable {
  6. private int color=Color.BLACK;
  7. MyColor(){
  8. color=Color.BLACK;
  9. }
  10. MyColor(Parcel in){
  11. color=in.readInt();
  12. }
  13. public int getColor(){
  14. return color;
  15. }
  16. public void setColor(int color){
  17. this.color=color;
  18. }
  19. @Override
  20. public int describeContents() {
  21. return 0;
  22. }
  23. @Override
  24. public void writeToParcel(Parcel dest, int flags) {
  25. dest.writeInt(color);
  26. }
  27. public static final Parcelable.Creator<MyColor> CREATOR
  28. = new Parcelable.Creator<MyColor>() {
  29. public MyColor createFromParcel(Parcel in) {
  30. return new MyColor(in);
  31. }
  32. public MyColor[] newArray(int size) {
  33. return new MyColor[size];
  34. }
  35. };
  36. }

MainActivity的代碼:

  1. package com.test;
  2. import android.app.Activity;
  3. import android.content.Intent;
  4. import android.graphics.Color;
  5. import android.os.Bundle;
  6. import android.view.MotionEvent;
  7. public class MainActivity extends Activity {
  8. private final int SUB_ACTIVITY=0;
  9. private MyColor color=new MyColor();
  10. @Override
  11. public void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.main);
  14. }
  15. @Override
  16. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  17. super.onActivityResult(requestCode, resultCode, data);
  18. if (requestCode==SUB_ACTIVITY){
  19. if (resultCode==RESULT_OK){
  20. if (data.hasExtra("MyColor")){
  21. color=data.getParcelableExtra("MyColor"); //<span style="font-size: 14px; white-space: pre;">反序列化后是一個新的MyColor對象</span>
  22. findViewById(R.id.text).setBackgroundColor(color.getColor());
  23. }
  24. }
  25. }
  26. }
  27. @Override
  28. public boolean onTouchEvent(MotionEvent event){
  29. if (event.getAction()==MotionEvent.ACTION_UP){
  30. Intent intent=new Intent();
  31. intent.setClass(this, SubActivity.class);
  32. color.setColor(Color.RED);
  33. intent.putExtra("MyColor", color);
  34. startActivityForResult(intent,SUB_ACTIVITY);
  35. }
  36. return super.onTouchEvent(event);
  37. }
  38. }

SubActivity的代碼:

  1. package com.test;
  2. import android.app.Activity;
  3. import android.content.Intent;
  4. import android.graphics.Color;
  5. import android.os.Bundle;
  6. import android.view.MotionEvent;
  7. import android.widget.TextView;
  8. public class SubActivity extends Activity {
  9. private MyColor color;
  10. @Override
  11. public void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.main);
  14. ((TextView)findViewById(R.id.text)).setText("SubActivity");
  15. Intent intent=getIntent();
  16. if (intent!=null){
  17. if (intent.hasExtra("MyColor")){
  18. color=intent.getParcelableExtra("MyColor");
  19. findViewById(R.id.text).setBackgroundColor(color.getColor());
  20. }
  21. }
  22. }
  23. @Override
  24. public boolean onTouchEvent(MotionEvent event){
  25. if (event.getAction()==MotionEvent.ACTION_UP){
  26. Intent intent=new Intent();
  27. if (color!=null){
  28. color.setColor(Color.GREEN);
  29. intent.putExtra("MyColor", color);
  30. }
  31. setResult(RESULT_OK,intent);
  32. finish();
  33. }
  34. return super.onTouchEvent(event);
  35. }
  36. }

在MainActivity的onActivityResult()中,有一句color=data.getParcelableExtra("MyColor"),這說明的是反序列化后是一個新的MyColor對象,因此要想使用這個對象,我們做了這個賦值語句。

如果數(shù)據(jù)本身是IBinder類型,那么反序列化的結(jié)果就是原對象,而不是新建的對象,很顯然,如果是這樣的話,在反序列化后在MainActivity中就不再需要color=data.getParcelableExtra("MyColor")這句了。因此,換一種MyColor的實現(xiàn)方法,令其中的int color成員變量使用IBinder類型的成員變量來表示。


新建一個BinderData類繼承自Binder,代碼如下:

  1. package com.test;
  2. import android.os.Binder;
  3. public class BinderData extends Binder {
  4. public int color;
  5. }

修改MyColor的代碼如下:

  1. package com.test;
  2. import android.graphics.Color;
  3. import android.os.Parcel;
  4. import android.os.Parcelable;
  5. public class MyColor implements Parcelable {
  6. private BinderData data=new BinderData();
  7. MyColor(){
  8. data.color=Color.BLACK;
  9. }
  10. MyColor(Parcel in){
  11. data=(BinderData) in.readValue(BinderData.class.getClassLoader());
  12. }
  13. public int getColor(){
  14. return data.color;
  15. }
  16. public void setColor(int color){
  17. data.color=color;
  18. }
  19. @Override
  20. public int describeContents() {
  21. return 0;
  22. }
  23. @Override
  24. public void writeToParcel(Parcel dest, int flags) {
  25. dest.writeValue(data);
  26. }
  27. public static final Parcelable.Creator<MyColor> CREATOR
  28. = new Parcelable.Creator<MyColor>() {
  29. public MyColor createFromParcel(Parcel in) {
  30. return new MyColor(in);
  31. }
  32. public MyColor[] newArray(int size) {
  33. return new MyColor[size];
  34. }
  35. };
  36. }

去掉MainActivity的onActivityResult()中的color=data.getParcelableExtra("MyColor")一句,變成:

  1. @Override
  2. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  3. super.onActivityResult(requestCode, resultCode, data);
  4. if (requestCode==SUB_ACTIVITY){
  5. if (resultCode==RESULT_OK){
  6. if (data.hasExtra("MyColor")){
  7. findViewById(R.id.text).setBackgroundColor(color.getColor());
  8. }
  9. }
  10. }
  11. }


    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多