版权声明:本文为HaiyuKing原创文章,转载请注明出处!

前言

简单记录下序列化Serializable和Parcelable的使用方法。

Android中Intent如果要传递类对象,可以通过两种方式实现

  • 方式一:Serializable,要传递的类实现Serializable接口传递对象,
  • 方式二:Parcelable,要传递的类实现Parcelable接口传递对象。

Serializable(Java自带):
Serializable是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。

Parcelable(android 专用):
除了Serializable之外,使用Parcelable也可以实现相同的效果,
不过不同于将对象进行序列化,Parcelable方式的实现原理是将一个完整的对象进行分解,
而分解后的每一部分都是Intent所支持的数据类型,这样也就实现传递对象的功能了。

实现序列化的作用

1)永久性保存对象,保存对象的字节序列到本地文件中;

2)通过序列化对象在网络中传递对象;

3)通过序列化在进程间传递对象。

选择序列化方法的原则

1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。

2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。

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

--摘自《序列化Serializable和Parcelable的理解和区别

 
简而言之:
Parcelable适合用在内存序列化上(也就是用于Intent间的数据传递);
Serializable适合用于将对象序列化到存储设备中或者将对象序列化后通过网络传输(一般用于Socket传输)。

使用方法

新建bean类

1、新建bean类implement Parcelable,重写以下方法

在Android Studio中可以自动引入:

package com.why.project.androidcnblogsdemo.bean;

import android.os.Parcel;
import android.os.Parcelable; /**
* Created by HaiyuKing
* Used 用户bean类
*/ public class UserBean implements Parcelable{
private String userName;
private int userId;
private boolean isVip; //必须要添加
public UserBean(){} public String getUserName() {
return userName;
} public void setUserName(String userName) {
this.userName = userName;
} public int getUserId() {
return userId;
} public void setUserId(int userId) {
this.userId = userId;
} public boolean isVip() {
return isVip;
} public void setVip(boolean vip) {
isVip = vip;
} //默认返回0就可以
//返回当前对象的内容描述,如果含有文件描述符,返回1,否则返回0,几乎所有情况都返回0
@Override
public int describeContents() {
return 0;
} //将你的对象序列化为一个Parcel对象 即:将类的数据写入外部提供的Parcel中,打包需要传递的数据到Parcel容器保存,以便从 Parcel容器获取数据
//将当前对象写入序列化结构中,其中flags标识有两种值:0或者1,为1时标识当前对象需要作为返回值返回,不能立即释放资源,几乎所有情况都为0
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(userName);
parcel.writeInt(userId);
parcel.writeByte((byte) (isVip ? 1 : 0));
} public static final Creator<UserBean> CREATOR = new Creator<UserBean>() {
//从序列化后的对象中创建原始对象
@Override
public UserBean createFromParcel(Parcel in) {
return new UserBean(in);
}
//创建指定长度的原始对象数组
@Override
public UserBean[] newArray(int size) {
return new UserBean[size];
}
};
//从序列化后的对象中创建原始对象
protected UserBean(Parcel in) {
userName = in.readString();
userId = in.readInt();
isVip = in.readByte() != 0;
}
}

2、新建bean类implement Serializable,手动指定serialVersionUID的值

不指定serialVersionUID也可以实现序列化,但是应该指定。这个serialVersionUID是用来辅助序列化和反序列化过程的,原则上序列化后的数据中的serialVersionUID只有和当前类的serialVersionUID相同才能够正常地被反序列化。serialVersionUID的详细工作机制是这样的:序列化的时候系统会将当前类的serialVersionUID写入序列化的文件中(也可能是其他中介),当反序列化的时候系统会检测文件中的serialVersionUID,看它是否和当前类的serialVersionUID一致,如果一致就说明序列化的类的版本和当前类的版本是相同的,这个时候可以成功反序列化;否则就说明当前类和序列化的类相比发生了某些变化,比如成员变量的数量、类型可能发生了改变,这个时候是无法正常反序列化的,因此会报错

而手动指定serialVersionUID值的话,序列化和反序列化时两者的serialVersionUID是相同的。如果不手动指定serialVersionUID的值,反序列化时当前类发生了改变,比如增加或者删除成员变量,那么系统就会重新计算当前类的hash值并把赋值给serialVersionUID,这个时候当前类的serialVersionUID就和序列化数据中的serialVersionUID不一致,于是反序列化失败。

--摘自《Android开发艺术探索》

package com.why.project.androidcnblogsdemo.bean;

import java.io.Serializable;

/**
* Created by HaiyuKing
* Used 书籍Bean类
*/ public class BookBean implements Serializable { private static final long serialVersionUID = 123L;//手动指定值,默认是1L,可以是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段 private String bookName;
private float bookPrice; public String getBookName() {
return bookName;
} public void setBookName(String bookName) {
this.bookName = bookName;
} public float getBookPrice() {
return bookPrice;
} public void setBookPrice(float bookPrice) {
this.bookPrice = bookPrice;
}
}

(1)通过序列化在进程间传递对象【使用Parcelable】

顺带演示Serializable的使用方法。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <Button
android:id="@+id/btn_intent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="通过序列化在进程间传递对象"
android:layout_margin="10dp"/> <Button
android:id="@+id/btn_savefile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="保存对象的字节序列到本地文件中"
android:layout_margin="10dp"/> <Button
android:id="@+id/btn_openfile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="反序列化从文件中读取对象数据"
android:layout_margin="10dp"/>
<TextView
android:id="@+id/tv_showbookInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>

activity_serialize_one.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="通过序列化Parcelable传递的对象数据"/> <TextView
android:id="@+id/tv_Parcelable"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"/> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="通过序列化Serializable传递的对象数据"/> <TextView
android:id="@+id/tv_Serializable"
android:layout_width="match_parent"
android:layout_height="wrap_content"/> </LinearLayout>

activity_serialize_two.xml

package com.why.project.androidcnblogsdemo.activity;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView; import com.why.project.androidcnblogsdemo.R;
import com.why.project.androidcnblogsdemo.bean.BookBean;
import com.why.project.androidcnblogsdemo.bean.UserBean; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; /**
* Created by HaiyuKing
* Used 序列化的首页界面
*/ public class SerializeOneActivity extends AppCompatActivity{ private UserBean mUserBean;
private BookBean mBookBean; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_serialize_one); initDatas();
initEvents(); } private void initDatas() {
mUserBean = new UserBean();
mUserBean.setUserId(1111);
mUserBean.setUserName("haiyuKing");
mUserBean.setVip(true); mBookBean = new BookBean();
mBookBean.setBookName("Android开发艺术探索");
mBookBean.setBookPrice(79f);
} private void initEvents() {
findViewById(R.id.btn_intent).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(SerializeOneActivity.this, SerializeTwoActivity.class);
Bundle bundle = new Bundle();
bundle.putParcelable("bundle_user",mUserBean);
bundle.putSerializable("bundle_book",mBookBean);
intent.putExtras(bundle);
startActivity(intent);
}
}); findViewById(R.id.btn_savefile).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) { }
}); findViewById(R.id.btn_openfile).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) { }
});
} }

接收:

package com.why.project.androidcnblogsdemo.activity;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView; import com.why.project.androidcnblogsdemo.R;
import com.why.project.androidcnblogsdemo.bean.BookBean;
import com.why.project.androidcnblogsdemo.bean.UserBean; /**
* Created by HaiyuKing
* Used 序列化的第二个界面
*/ public class SerializeTwoActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_serialize_two); TextView tv_Parcelable = findViewById(R.id.tv_Parcelable);
TextView tv_Serializable = findViewById(R.id.tv_Serializable); UserBean userBean = (UserBean)getIntent().getParcelableExtra("bundle_user");
BookBean bookBean = (BookBean)getIntent().getSerializableExtra("bundle_book"); tv_Parcelable.setText(userBean.getUserId()+";"+userBean.getUserName()+";"+userBean.isVip());
tv_Serializable.setText(bookBean.getBookName()+";"+bookBean.getBookPrice());
}
}

效果图

(2)保存对象的字节序列到本地文件中【使用Serializable】

package com.why.project.androidcnblogsdemo.activity;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView; import com.why.project.androidcnblogsdemo.R;
import com.why.project.androidcnblogsdemo.bean.BookBean;
import com.why.project.androidcnblogsdemo.bean.UserBean; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream; /**
* Created by HaiyuKing
* Used 序列化的首页界面
*/ public class SerializeOneActivity extends AppCompatActivity{ private UserBean mUserBean;
private BookBean mBookBean; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_serialize_one); initDatas();
initEvents(); } private void initDatas() {
mUserBean = new UserBean();
mUserBean.setUserId(1111);
mUserBean.setUserName("haiyuKing");
mUserBean.setVip(true); mBookBean = new BookBean();
mBookBean.setBookName("Android开发艺术探索");
mBookBean.setBookPrice(79f);
} private void initEvents() {
findViewById(R.id.btn_intent).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) { }
}); findViewById(R.id.btn_savefile).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
//文件存放的位置在 /data/data/<package>/files 下
File file = new File(SerializeOneActivity.this.getFilesDir().getPath(), "cache.txt");
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
out.writeObject(mBookBean);
out.close();
} catch (IOException e) {
e.printStackTrace();
} }
}); findViewById(R.id.btn_openfile).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
//文件存放的位置在 /data/data/<package>/files 下
File file = new File(SerializeOneActivity.this.getFilesDir().getPath(), "cache.txt");
ObjectInputStream out = new ObjectInputStream(new FileInputStream(file));
BookBean newBookBean = (BookBean) out.readObject();//内容一致,但不是同一个对象
out.close(); TextView tv_showbookInfo = findViewById(R.id.tv_showbookInfo);
tv_showbookInfo.setText(newBookBean.getBookName()+";"+newBookBean.getBookPrice());
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} }
});
} }

cache.txt的路径:

效果图:

(3)将对象序列化后通过网络传输【使用Serializable】

暂时空缺

参考资料

序列化Serializable和Parcelable的理解和区别

《Android开发艺术探索》

Android中Parcelable接口用法

Android 读写文件 FileNotFoundException 异常

序列化Serializable和Parcelable的更多相关文章

  1. 转 序列化Serializable和Parcelable的区别详解

    什么是序列化,为什么要进行序列化 答:对象要进行传输(如:activity 与activity间 ,网络间 进程间等等).存储到本地就必须进行序列化 . 这种可传输的状态就是序列化. 怎么序列化??两 ...

  2. Android序列化之Serializable和Parcelable

    PS:还有几天就开学了.先来一发. 学习内容: 1.序列化的目的 2.Android中序列化的两种方式 3.Parcelable与Serializable的性能比较 4.Android中如何使用Par ...

  3. Android中Serializable和Parcelable序列化对象详解

    学习内容: 1.序列化的目的 2.Android中序列化的两种方式 3.Parcelable与Serializable的性能比较 4.Android中如何使用Parcelable进行序列化操作 5.P ...

  4. Serializable 和 Parcelable 区别

    http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0204/2410.html http://www.cnblogs.com/blu ...

  5. 浅谈Android中Serializable和Parcelable使用区别

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.概述 Android开发的时候,我们时长遇到传递对象的需求,但是我们无法将对象的引用传给Activity或者Fragment,我们需要将这些对象 ...

  6. Serializable 和 parcelable的实现和比较

    首先这个两个接口都是用来序列化对象的 但是两者在性能和应用场合上有区别,parcelable的性能更好,但是在需要保存或者网络传输的时候需要选择Serializable因为parcelable版本在不 ...

  7. Serializable和Parcelable的简单介绍

    Serializable和Pacelable接口可以完成对象的序列化过程,当我们需要通过Intent和Binder传输数据时就需要使用Parcelable或者Serializable. Seriali ...

  8. Intent传递对象——Serializable和Parcelable差别

    前两篇文章讨论了Serializable和Parcelable实现Intent之间传递对象和对象数组的方式.两种方法实现上相似,效果一致,怎么选择用哪种方法实现呢? Intent在不同的组件中传递对象 ...

  9. Serializable 和Parcelable 详解

    序列化:为了保存在内存中的各种对象的状态,并可以把保存的对象的状态读出来 安卓中实现序列化的接口有两个,一个是serializable,一个是parcelable. 一.实现序列化: 1.是可以将对象 ...

随机推荐

  1. onenote使用教程

    1. OneNote的基础功能 随处可以记录笔记 收集页面 微信关注公众号 [微软云笔记] IE和Chrome等浏览器扩展-OneNote Clipper 通过绘图实现手绘效果 插入音频与视频 实现多 ...

  2. python中for嵌套打印图形

    # 打印出九九乘法表 1 * 1 = 1 2 * 1 = 2 2 * 2 = 4 3 * 1 = 3 3 * 2 = 6 3 * 3 = 9 4 * 1 = 4 4 * 2 = 8 4 * 3 = 1 ...

  3. GDB 调试 C++ 程序 core dump

    https://blog.csdn.net/yockie/article/details/51973740

  4. 变量前缀__device__以及__managed__

    1.__device__ 作为变量前缀时,__device__限定符声明位于设备上的变量.如果此限定符单独使用,则变量具有以下特征: a.位于全局存储器空间中: b.与应用程序具有相同的生命周期: 可 ...

  5. 记一次非常规方法对接硬件设备(Grason Stadler GSI 61)

    Grason Stadler GSI 61 电测听设备 (写下设备的名字, 希望别人遇坑可以搜到) 对接说明 设备厂家提供自带的软件,但是没有找到接口说明.我们需要获取设备发送过来的数据. 厂家提供的 ...

  6. c++链表基本操作

    #include <stdlib.h> #include <malloc.h> #include <stdio.h> typedef struct Node { i ...

  7. swust oj 1011

    二叉排序树的实现和查找 1000(ms) 10000(kb) 2782 / 6301 按照给定的关键字集合,建立二叉排序树.在建立的二叉排序树上查找指定的关键字,查找成功,输出找到该关键字比较的次数: ...

  8. HTML块元素,行内元素,类,头部元素

    总结HTML块元素,行内元素,类,头部元素 块元素: 在HTML中,块级元素的高度为其内容的高度,宽度会扩展到与父容器同宽.默认情况下,块级元素会独占一行,并且元素前后行留空. 示例:<h1&g ...

  9. [文章汇总]ASP.NET Core框架揭秘[最近更新:2018/10/31]

    之前一段时间都在个人公众号账号“大内老A”发布关于ASP.NET Core的系列文章,很多人留言希望能够同步到这里,所以在这里 对这些文章做一个汇总,以便于PC端阅读.如果说微软官方文档主要关于ASP ...

  10. 255.Spring Boot+Spring Security:使用md5加密

    说明 (1)JDK版本:1.8 (2)Spring Boot 2.0.6 (3)Spring Security 5.0.9 (4)Spring Data JPA 2.0.11.RELEASE (5)h ...