Android中的Parcel和Parcelable

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

 

Parcel 在英文中有两个意思,其一是名词,为包裹,小包的意思; 其二为动词,意为打包,扎包。邮寄快递中的包裹也用的是这个词。Android采用这个词来表示封装消息数据。这个是通过IBinder通信的消息的载体。需要明确的是Parcel用来存放数据的是内存(RAM),而不是永久性介质(Nand等)。

 

Parcelable,定义了将数据写入Parcel,和从Parcel中读出的接口。一个实体(用类来表示),如果需要封装到消息中去,就必须实现这一接口,实现了这一接口,该实体就成为“可打包的”了。

 

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从流里读取对象,只不过这个过程需要你来实现,因此写的顺序和读的顺序必须一致。 clip_image002

在实现Parcelable的实现中,规定了必须定义一个静态成员, 初始化为嵌入接口的实现类。

 

Intent 可以携带对象来在不同的Activity中传递数据,要传递的数据必须实现三个方法

1. describeContents()返回0就可以

2. writeToParcel(Parcel parcel, int flag) 把需要写入的数据写入Parcel中,然后框架调用此方法发送给接收端的Activity

3. public static final Parcelable.Creator<ParcelableObject> CREATOR 外部类反序列化该类时调用此方法

一定要注意:写入parcel和反序列化parcel时顺序一定要相同,不然数据会出错

 

案例介绍:

/**  
 * ParcelableObject.java  
 * com.androidtest.parcelable  
 *  
 * Function: TODO  
 *  
 *   ver     date           author  
 * ──────────────────────────────────  
 *           2011-5-11      Leon  
 *  
 * Copyright (c) 2011, TNT All Rights Reserved.  
*/  
   
package com.androidtest.parcelable;  
   
import android.os.Parcel;  
import android.os.Parcelable;  
   
/**  
 * ClassName:ParcelableObject 需要实现三个方法,describeContents()返回0就可以 、 writeToParcel(Parcel parcel, int flag)  
 * 写入Parcel和public static final Parcelable.Creator  
<parcelableobject><span style="font-size: 14px"> CREATOR 供外部类反序列化该类  
 * 一定要注意顺序后面这个两个函数读和写的顺序要相同,不然数据会出错  
 * Function: TODO  
 * Reason:   TODO ADD REASON  
 *  
 * @author   Leon  
 * @version  
 * @since    Ver 1.1  
 * @Date     2011-5-11  
 */  
public class ParcelableObject implements Parcelable{  
    private  String  name  ;  
    private  String  surName ;  
    private  int     age ;   
   
    public String getName() {  
        return name;  
    }  
   
    public void setName(String name) {  
        this.name = name;  
    }  
   
    public String getSurName() {  
        return surName;  
    }  
   
    public void setSurName(String surName) {  
        this.surName = surName;  
    }  
   
    public int getAge() {  
        return age;  
    }  
   
    public void setAge(int age) {  
        this.age = age;  
    }  
   
    @Override  
    public int describeContents() {  
   
        // TODO Auto-generated method stub  
        return 0;  
   
    }  
   
    @Override  
    public void writeToParcel(Parcel dest, int flag) {  
   
        // TODO Auto-generated method stub  
   
        dest.writeInt(age);  
        dest.writeString(name);  
        dest.writeString(surName);  
   
    }  
    public static final Parcelable.Creator CREATOR = new Creator() {  
   
        @Override  
        public ParcelableObject createFromParcel(Parcel source) {  
   
            // TODO Auto-generated method stub  
            ParcelableObject parcelableObj = new ParcelableObject();  
            parcelableObj.age=source.readInt();  
            parcelableObj.surName=source.readString();  
            parcelableObj.name = source.readString();  
            return parcelableObj;  
   
        }  
   
        @Override  
        public ParcelableObject[] newArray(int size) {  
   
            // TODO Auto-generated method stub  
            return new ParcelableObject[size];  
   
        }   
   
    };  
} 

ParcelableActivity1 发送的代码:

package com.androidtest.parcelable;  
   
import android.app.Activity;  
import android.content.Intent;  
import android.os.Bundle;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.widget.Button;  
import android.widget.LinearLayout;  
public class ParcelableActivity1 extends Activity {  
   
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        // TODO Auto-generated method stub  
        super.onCreate(savedInstanceState);  
        LinearLayout linearLayout = new LinearLayout(this);  
        Button button = new Button(this);  
        button.setText("Send Parcelable Object");  
        linearLayout.addView(button);  
        button.setOnClickListener(new OnClickListener(){  
            @Override  
            public void onClick(View arg0) {  
                ParcelableObject passObject = new ParcelableObject();  
                passObject.setName("Leon Zhang");  
                passObject.setAge(18);  
                passObject.setSurName("xxx");  
   
                Intent intent = new Intent(ParcelableActivity1.this,ParcelableActivity2.class);  
//              使用Bundle发送  
//              Bundle bundle = new Bundle();  
//              bundle.putParcelable("key", passObject);  
                intent.putExtra("key", passObject);  
//              intent.putExtras(bundle);  
                intent.putExtra("key2", "out of bundle");  
                startActivity(intent);  
            }  
        });  
       this.setContentView(linearLayout);  
    }  
   
} 

ParcelableActivity2 接收的代码:

package com.androidtest.parcelable;  
   
import android.app.Activity;  
import android.os.Bundle;  
import android.util.Log;  
   
public class ParcelableActivity2 extends Activity {  
   
    private static final String TAG = ParcelableActivity2.class.getSimpleName();  
   
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
   
        // TODO Auto-generated method stub  
        super.onCreate(savedInstanceState);  
        ParcelableObject passObject = this.getIntent()  
                .getParcelableExtra("key");  
   
        Log.v(TAG, "Name: " + passObject.getName() + " Surname: "  
                        + passObject.getSurName() + " Age: "  
                        + String.valueOf(passObject.getAge())  
                        + " out of bundle is :"  
                        + this.getIntent().getStringExtra("key2"));  
        Bundle myBundle = this.getIntent().getExtras();  
        Log.v(TAG,"XX: "  
                        + ((ParcelableObject) myBundle.getParcelable("key"))  
                                .getName()+ " Key2 :"+ myBundle.getString("key2"));  
   
    }  
   
} 

经过测试发现,当使用Intent传递数据时,如果你自己创建了一个Bundle,则无论要传的数据是否放入Bundle(如直接intent.putExtra("xx" , "xx")),都会放到放到此Bundle中。如果没有创建此Bundle,则会默认创建一个Bundle来存放数据。当取数据时可以先取Bundle再从Bundle中取数据,或者直接取就好了。

 

参考:

http://zuiniuwang.blog.51cto.com/3709988/718330

http://www.2cto.com/kf/201205/132814.html

http://blog.youkuaiyun.com/dairyman000/article/details/7247619

转载于:https://www.cnblogs.com/kevinhigher/archive/2012/10/06/2712733.html

内容概要:本文档是一份基于最新Java技术趋势的实操指南,涵盖微服务架构(Spring Cloud Alibaba)、响应式编程(Spring WebFlux + Reactor)、容器化与云原生(Docker + Kubernetes)、函数式编程与Java新特性、性能优化与调优以及单元测试与集成测试六大技术领域。针对每个领域,文档不仅列出了面试中的高频考点,还提供了详细的实操场景、具体实现步骤及示例代码。例如,在微服务架构中介绍了如何利用Nacos进行服务注册与发现、配置管理,以及使用Sentinel实现熔断限流;在响应式编程部分展示了响应式控制器开发、数据库访问流处理的方法;对于容器化,则从Dockerfile编写到Kubernetes部署配置进行了讲解。 适合人群:具有一定的Java编程基础,尤其是正在准备面试或希望深入理解并掌握当前主流Java技术栈的研发人员。 使用场景及目标:①帮助求职者熟悉并能熟练运用微服务、响应式编程等现代Java开发技术栈应对面试;②指导开发者在实际项目中快速上手相关技术,提高开发效率技术水平;③为那些想要深入了解Java新特性最佳实践的程序员提供有价值的参考资料。 阅读建议:由于文档内容丰富且涉及多个方面,建议读者按照自身需求选择感兴趣的主题深入学习,同时结合实际项目进行练习,确保理论与实践相结合。对于每一个技术点,不仅要关注代码实现,更要理解背后的原理应用场景,这样才能更好地掌握这些技能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值