Android中的Parcelable

来源:互联网 发布:最穷的时候知乎 编辑:程序博客网 时间:2024/06/16 02:26

android.os.Parcelable

 对于Android来说传递复杂类型,主要是将自己的类转换为基础的字节数组,Activity之间传递数据是通过Intent实现的。 Android序列化对象主要有两种方法,实现Serializable接口、或者实现Parcelable接口。实现Serializable接口是Java SE本身就支持的,而Parcelable是Android特有的功能,效率比实现Serializable接口高,而且还可以用在进程间通信(IPC)中。实现Serializable接口非常简单,声明一下就可以了。而实现Parcelable接口稍微复杂一些,但效率更高,推荐用这种方法提高性能。


 Parcelable接口的作用:实现了Parcelable接口的实例可以将自身的状态信息(状态信息通常指的是各成员变量的值)写入Parcel,也可以从Parcel中恢复其状态。 Parcel用来完成数据的序列化传递。下面就介绍一下实现Parcelable接口的方法。


 通过实现Parcelable接口序列化对象的步骤:


 1、实现Parcelable接口。
 2、并且实现Parcelable接口的public
 void writeToParcel(Parcel dest, int flags)方法 。
 3、自定义类型中必须含有一个名称为CREATOR的静态成员,该成员对象要求实现Parcelable.Creator接口及其方法。
 简而言之:通过writeToParcel将你的对象映射成Parcel对象,再通过createFromParcel将Parcel对象映射成你的对象。也可以将Parcel看成是一个流,通过writeToParcel把对象写到流里面,在通过createFromParcel从流里读取对象,只不过这个过程需要你来实现,因此写的顺序和读的顺序必须一致。

 Parcelable实现要点:需要实现三个东西


 1)writeToParcel 方法。该方法将类的数据写入外部提供的Parcel中.声明如下:

 writeToParcel (Parcel dest, int flags) 具体参数含义见javadoc

 2)describeContents方法。没搞懂有什么用,反正直接返回0也可以

 3)静态的Parcelable.Creator接口,本接口有两个方法:

 createFromParcel(Parcel in) 实现从in中创建出类的实例的功能 newArray(int size) 创建一个类型为T,长度为size的数组,仅一句话(return new T[size])即可。估计本方法是供外部类反序列化本类数组使用。

eg:

 public class MyParcelable implements Parcelable {     private int mData;     public int describeContents() {         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 new MyParcelable[size];         }     };          private MyParcelable(Parcel in) {         mData = in.readInt();     } }

序列化原因:


 1.永久性保存对象,保存对象的字节序列到本地文件中;
 2.通过序列化对象在网络中传递对象;
 3.通过序列化在进程间传递对象。

至于选取哪种可参考下面的原则:


 1.在使用内存的时候,Parcelable 类比Serializable性能高,所以推荐使用Parcelable类。
 2.Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
 3.Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点, 也不提倡用,但在这种情况下,还是建议你用Serializable 。

作用

 android提供了一种新的类型:Parcel。本类被用作封装数据的容器,封装后的数据可以通过Intent或IPC传递。 除了基本类型以外,只有实现了Parcelable接口的类才能被放入Parcel中。

 而对于Intent还有Bundle,他们只能携带的数据有八种基本类型,还有String,其实String实现了Serializable,即还有实现接口Serializable或者Parcelable类型的类都可以。否则,当数据过多时,需要用一个类(结构)封装数据,该类需要实现Serializable或者Parcelable。
 既可以通过以下方法进行数据封装:
 Intent:
 intent.putExtra(String name, Serializable value)
 intent.putExtra(String name, Parcelable value)
 intent.putExtra(String name, Parcelable[] value)      
 intent.putParcelableArrayListExtra(String name, ArrayList<? extends Parcelable> value)
 intent.getSerializableExtra(name)
 intent.getParcelableArrayExtra(name)
 intent.getParcelableArrayListExtra(name)
 intent.getParcelableExtra(name)

 Bundle:
 data.putSerializable(key, value)
 data.putParcelable(key, value)
 data.putParcelableArray(key, value)
 data.putParcelableArrayList(key, value)
 data.getSerializable(key)
 data.getParcelable(key)
 data.getParcelableArray(key)
 data.getParcelableArrayList(key)


一个例子:

MainActivity.java

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent intent = getIntent();//可以直接获取INtent,为何还要new Intent???
        Person p = new Person();
        p.map = new HashMap<String, String>();
        p.map.put("yes", "ido");
        p.name = "ok";
        intent.putExtra("yes", p);
        intent.setClass(this, Test.class);
        startActivity(intent);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

Test.java

public class Test extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);

        Intent i = getIntent();
        Person p = i.getParcelableExtra("yes");

        Log.d("nimeimei", "name=" + p.name + "," + "size=" + p.map.size());

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.test, menu);
        return true;
    }

}

Person.java

public class Person implements Parcelable {

    public HashMap<String, String> map = new HashMap<String, String>();

    public String name;

    @Override
    public int describeContents() {

        Log.d("nimeimei", "0000000000000000describeContents");
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {

        Log.d("nimeimei", "111111111111111111111111111writeToParcel");
        dest.writeMap(map);
        dest.writeString(name);
    }

    public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
        // 重写Creator

        @Override
        public Person createFromParcel(Parcel source) {

            Log.d("nimeimei", "11111111111111111111111111createFromParcel");
            Person p = new Person();
            p.map = source.readHashMap(HashMap.class.getClassLoader());
            p.name = source.readString();

            Log.d("nimeimei", "11111111111111111111111111createFromParcel"
                    + p.map);

            return p;
        }

        @Override
        public Person[] newArray(int size) {
            // TODO Auto-generated method stub
            return null;
        }
    };

}




原创粉丝点击