Parcelable实战

Parcelable实战Android 开发过程中 无法将对象的引用传给 Activities 或者 Fragments 我们需要将这些对象放到一个 Intent 或者 Bundle 里面 然后再传递 这就需要用到序列化和反序列化 序列化分类 Parcelable 原理 Parcelable 使用回调接口传递注意事项序列化分类 Serializable 是 java 的序列化技术 使用简单 频繁的 IO 操作 效率低 P

Android开发过程中,无法将对象的引用传给Activities或者Fragments,我们需要将这些对象放到一个Intent或者Bundle里面,然后再传递,这就需要用到序列化和反序列化。

  • 序列化分类
  • Parcelable原理
  • Parcelable使用
  • 回调接口传递
  • 注意事项

序列化分类

(1)Serializable 是java的序列化技术,使用简单,频繁的IO操作,效率低

(2)Parcelable 是Android为我们提供的序列化的接口,使用稍微复杂,内存操作,效率高

(3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable在外界有变化的情况下不能很好的保证数据的持续性。尽管Serializable效率低点,但此时还是建议使用Serializable。存储到设备或者网络传输上选择Serializable。

Parcelable原理

(1)Parcelable是Android特有的序列化API,它的出现是为了解决Serializable在序列化的过程中消耗资源严重的问题,但是因为本身使用需要手动处理序列化和反序列化过程,会与具体的代码绑定,使用较为繁琐,一般只获取内存数据的时候使用。

Parcelable使用

1、首先创建一个ParcelBean对象,继承自Parcelable,这个就是我们要将其序列化的对象,对象里边的属性有数值、boolean、字符串、对象、数组和链表等各种类型,重点是看下各种类型的序列化和反序列化的方式。

import android.os.Parcel; import android.os.Parcelable; import java.util.ArrayList; import java.util.List; public class ParcelBean implements Parcelable{ 
    public int count; public boolean flag; public String name; public ParcelItemBean itemBean; public List<ParcelItemBean> itmeList = new ArrayList<>(); public String[] array; //回调接口对象 public ParcelCallbackBean parcelCallbackBean; public ParcelBean() { 
    super(); } public ParcelBean(Parcel source) { 
    super(); count = source.readInt(); flag = source.readByte() != 0; name = source.readString(); itemBean= source.readParcelable(ParcelItemBean.class.getClassLoader()); // 读取对象需要提供一个类加载器去读取,因为写入的时候写入了类的相关信息 source.readTypedList(itmeList, ParcelItemBean.CREATOR); //对应writeTypeList array = source.createStringArray(); //回调接口 parcelCallbackBean= source.readParcelable(ParcelCallbackBean.class.getClassLoader()); } public static final Creator<ParcelBean> CREATOR = new Creator<ParcelBean>() { 
    @Override public ParcelBean createFromParcel(Parcel in) { 
    return new ParcelBean(in); } @Override public ParcelBean[] newArray(int size) { 
    return new ParcelBean[size]; } }; @Override public int describeContents() { 
    return 0; } @Override public void writeToParcel(Parcel dest, int flags) { 
    dest.writeInt(count); dest.writeByte((byte) (flag ? 1 : 0)); dest.writeString(name); dest.writeParcelable(itemBean, flags); dest.writeTypedList(itmeList); dest.writeStringArray(array); //回调接口对象 dest.writeParcelable(parcelCallbackBean, flags); } } 

2、里边有一个ParcelItemBean的子对象,如下

import android.os.Parcel; import android.os.Parcelable; public class ParcelItemBean implements Parcelable { 
    public String itemName; public ParcelItemBean(){ 
    super(); } protected ParcelItemBean(Parcel in) { 
    super(); itemName = in.readString(); } public static final Creator<ParcelItemBean> CREATOR = new Creator<ParcelItemBean>() { 
    @Override public ParcelItemBean createFromParcel(Parcel in) { 
    return new ParcelItemBean(in); } @Override public ParcelItemBean[] newArray(int size) { 
    return new ParcelItemBean[size]; } }; @Override public int describeContents() { 
    return 0; } @Override public void writeToParcel(Parcel dest, int flags) { 
    dest.writeString(itemName); } } 

3、对象序列化后需要通过Activity来加到ParcelableActivity的Intent中发送出去

import java.util.ArrayList; public class ParcelableActivity extends AppCompatActivity implements View.OnClickListener { 
    @Override protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); setContentView(R.layout.activity_parcelable); initView(); } private void initView() { 
    findViewById(R.id.parcel).setOnClickListener(this); } @Override public void onClick(View v) { 
    switch (v.getId()) { 
    case R.id.parcel: parcelSend(); break; default: break; } } private void parcelSend() { 
    ParcelBean parcelBean = new ParcelBean(); parcelBean.name = "lisi"; parcelBean.flag = false; parcelBean.count = 66; //写入对象 ParcelItemBean parcelItemBean = new ParcelItemBean(); parcelItemBean.itemName = "itmeNNN"; parcelBean.itemBean = parcelItemBean; //写入list ParcelItemBean itemBean1 = new ParcelItemBean(); itemBean1.itemName = "item111"; ParcelItemBean itemBean2 = new ParcelItemBean(); itemBean2.itemName = "item222"; ArrayList<ParcelItemBean> beanList = new ArrayList<>(); beanList.add(itemBean1); beanList.add(itemBean2); parcelBean.itmeList = beanList; //写入数组 String array[] = new String[]{ 
   "num1", "num2", "num3"}; parcelBean.array = array; //写入回调接口 ParcelCallbackListenerBinder.CallbackListener callbackListener = new ParcelCallbackListenerBinder.CallbackListener() { 
    @Override public void onComplete(Object obj) { 
    Log.d("parcel_call_back", "callBackComplete"); } @Override public void onError(String msg) { 
    Log.d("parcel_call_back", "callBackError"); } @Override public void onCancel() { 
    Log.d("parcel_call_back", "callBackCancel"); } }; ParcelCallbackListenerBinder.ClickCallbackListener clickCallbackListener = new ParcelCallbackListenerBinder.ClickCallbackListener() { 
    @Override public void onClick(String channel) { 
    Log.d("parcel_call_back", "clickCallBack"+channel); } }; ParcelCallbackBean parcelCallbackBean = new ParcelCallbackBean(new ParcelCallbackListenerBinder(callbackListener, clickCallbackListener)); parcelBean.parcelCallbackBean = parcelCallbackBean; Intent intent = new Intent(this, ParcelReceiveActivity.class); intent.putExtra("keyName", "zhangsan"); intent.putExtra("parcel", parcelBean); startActivity(intent); } } 

4、上面是发送的Activity,还需要一个接收的ParcelReceiveActivity

 public class ParcelReceiveActivity extends AppCompatActivity implements View.OnClickListener { 
    ParcelCallbackBean mParcelCallbackBean; @Override protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); setContentView(R.layout.activity_parcel_receive); initView(); } private void initView() { 
    findViewById(R.id.click_callback).setOnClickListener(this); Intent intent = getIntent(); Log.d("ParcelReceiveActivity", "keyName = "+intent.getStringExtra("keyName")); ParcelBean parcelBean = intent.getParcelableExtra("parcel"); Log.d("ParcelReceiveActivity", "parcelBean.name = "+parcelBean.name); Log.d("ParcelReceiveActivity", "parcelBean.flag = "+parcelBean.flag); Log.d("ParcelReceiveActivity", "parcelBean.count = "+parcelBean.count); Log.d("ParcelReceiveActivity", "parcelBean.itemBean.itemName = "+parcelBean.itemBean.itemName); Log.d("ParcelReceiveActivity", "parcelBean.itmeList.get(0).itemName = "+parcelBean.itmeList.get(0).itemName); Log.d("ParcelReceiveActivity", "parcelBean.itmeList.get(1).itemName = "+parcelBean.itmeList.get(1).itemName); Log.d("ParcelReceiveActivity", "parcelBean.array[0] = "+parcelBean.array[0]); Log.d("ParcelReceiveActivity", "parcelBean.array[1] = "+parcelBean.array[1]); //获取传递过来的接口对象 mParcelCallbackBean = parcelBean.parcelCallbackBean; } @Override public void onClick(View v) { 
    switch (v.getId()) { 
    case R.id.click_callback: clickCallBack(); break; default: break; } } private void clickCallBack() { 
    mParcelCallbackBean.parcelCallbackListenerBinder.getClickCallbackListener().onClick("我是传递过来的点击事件"); } } 

5、在接收的Activity里边打印Log,如下

 ParcelReceiveActivity: keyName = zhangsan parcelBean.name = lisi parcelBean.flag = false parcelBean.count = 66 parcelBean.itemBean.itemName = itmeNNN parcelBean.itmeList.get(0).itemName = item111 parcelBean.itmeList.get(1).itemName = item222 parcelBean.array[0] = num1 parcelBean.array[1] = num2 

回调接口传递

上面有一个回调接口的对象的传递,这里单独拿出来说一下,首先建立一个ParcelCallbackListenerBinder对象,继承自Binder,用来管理这两个回调接口

import android.os.Binder; public class ParcelCallbackListenerBinder extends Binder{ 
    public CallbackListener callbackListener; public ClickCallbackListener clickCallbackListener; public ParcelCallbackListenerBinder(CallbackListener callbackListener, ClickCallbackListener clickCallbackListener) { 
    this.callbackListener = callbackListener; this.clickCallbackListener = clickCallbackListener; } public CallbackListener getCallbackListener() { 
    return callbackListener; } public ClickCallbackListener getClickCallbackListener() { 
    return clickCallbackListener; } public static interface CallbackListener { 
    void onComplete(Object obj); void onError(String msg); void onCancel(); } public static interface ClickCallbackListener { 
    void onClick(String channel); } } 

然后再将这个封装的回调接口,封装到ParcelCallbackBean中,这个也是继承自Parcelable的

import android.os.Parcel; import android.os.Parcelable; import com.jd.test.phototest.activity.interfac.ParcelCallbackListenerBinder; public class ParcelCallbackBean implements Parcelable{ 
    public ParcelCallbackListenerBinder parcelCallbackListenerBinder; public ParcelCallbackBean(ParcelCallbackListenerBinder binder) { 
    parcelCallbackListenerBinder = binder; } protected ParcelCallbackBean(Parcel source) { 
    Object object = source.readValue(ParcelCallbackListenerBinder.class.getClassLoader()); if (object instanceof ParcelCallbackListenerBinder) { 
    parcelCallbackListenerBinder = (ParcelCallbackListenerBinder) object; } } public static final Creator<ParcelCallbackBean> CREATOR = new Creator<ParcelCallbackBean>() { 
    @Override public ParcelCallbackBean createFromParcel(Parcel in) { 
    return new ParcelCallbackBean(in); } @Override public ParcelCallbackBean[] newArray(int size) { 
    return new ParcelCallbackBean[size]; } }; @Override public int describeContents() { 
    return 0; } @Override public void writeToParcel(Parcel dest, int flags) { 
    dest.writeValue(parcelCallbackListenerBinder); } } 

在ParcelReceiveActivity里进行回调,通过clickCallBack方法进行回调,在ParcelableActivity里进行回调的接收。我们来看一下点击回调的结果

parcel_call_back: clickCallBack我是传递过来的点击事件 parcel_call_back: clickCallBack我是传递过来的点击事件 parcel_call_back: clickCallBack我是传递过来的点击事件 

注意事项

(1)Parcelable使用的时候要注意ParcelBean和writeToParcel也就是读写时各个属性的顺序,一定要一致,不然会存在问题。

(2)接口回调的ParcelCallbackListenerBinder类要继承自Binder,这个问啥我还没搞清楚,猜测应该和Parcelable底层使用的Binder进程通信有关,欢迎各位大佬指教。

尊重作者,尊重原创,参考文章:
https://www.jianshu.com/p/df35baa91541
https://blog.csdn.net/hacker_crazy/article/details/
https://www.cnblogs.com/tangZH/p/10998065.html






版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/227983.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午8:03
下一篇 2026年3月16日 下午8:04


相关推荐

  • 电信光纤友华PT921G,烽火HG220光猫激活成功教程关闭自带路由改桥接拨号教程「建议收藏」

    电信光纤友华PT921G,烽火HG220光猫激活成功教程关闭自带路由改桥接拨号教程「建议收藏」电信光纤友华PT921G光猫激活成功教程关闭自带路由改桥接拨号教程电信光猫质量烂就算了,最受不了它自带的路由还做了手脚,导致VPN用不了。不让看AV就算了,打个外服游戏总可以吧?不知道为啥,网上关于光猫改桥接的教程基本没有,搜出来的也说得很不清楚,是和谐了还是什么原因不得而知。本人也是自己自己试出来的,其实修改难度并不大,只不过那个界面搞的特奇葩特不友好罢了。废话不多说,步骤如下:

    2022年6月27日
    175
  • pycharm如何配置_网络配置异常怎么修复

    pycharm如何配置_网络配置异常怎么修复PyCharm配置示例1、全局设置:这里是全局设置,也可在每个项目里面单独设置点击右下角的Configure选择Preferences1、设置背景颜色与显示内存大小:2、设置不默认打开上次的工程3、设置显示方法右边分割线:4、设置自动引包:5、设置显示方法缩进线6、设置字体与字体大小:7、设置文件编码格式:请注意,这一步很重要,不要坑队友!8、测试本机是…

    2022年8月28日
    5
  • linux下开放oracle1521端口以便于远程连接

    linux下开放oracle1521端口以便于远程连接   1,利用root账号登录linux,输入命令:serviceiptablesstop(先把oracle防火墙给关闭)。   2.输入命令:vi /etc/sysconfig/iptables,在里面添加如下一行:      -A RH-Firewall-1-INPUT -p tcp -m state –state NEW -m tcp –dport …

    2022年6月3日
    39
  • Windows 11系统OpenClaw(龙虾)安装教程|保姆级一步到位

    Windows 11系统OpenClaw(龙虾)安装教程|保姆级一步到位

    2026年3月13日
    4
  • 数据结构 图的邻接矩阵

    数据结构 图的邻接矩阵图的邻接矩阵的存储方式是用两个数组来实现的,一个一维数组存储顶点信息,一个二维数组存储线(无向图)或弧(有向图)的信息。设图G有n个顶点,则邻接矩阵是一个n×n的方阵,定义为:无向图的邻接矩阵,两个顶点有边则为1,否则,为0;因为是无向图arc[i][j]=arc[j][i],所以矩阵为对称矩阵,对角线为自己到自己的边,邻接矩阵中,行之和或者列之和都为各顶点度的总数。设图G有是网图,有n个…

    2022年6月28日
    24
  • goland 激活【2021免费激活】

    (goland 激活)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html1M…

    2022年3月28日
    71

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号