parcelable序列化 :对象,数组,boolean,bitmap;
一、序列化分为:序列化过程 和 反序列化过程:
一)序列化过程:
//序列化过程 一系列write方法
//其中flags标识有两种值:0或者1,
// 1 === 标识当前对象需要作为返回值返回,
// 0 === 不能立即释放资源,几乎所有情况都为0
public void writeToParcel(Parcel out,int flags){
out.writeInt(...);
out.writeString(...);
out.writeInt(isMan?1:0);
out.writeParcelable(son,0);
}
二)反序列化:
//反序列化过程
public static final Parcelable.Creator<Person> CREATOR=new Parcelable.Creator<Person>(){
//从序列化后的对象中创建原始对象
public Person createFromParcel(Parcel in){
return new Person(in);
}
//创建指定长度的原始对象数组
public Person[] newArray(int size){
return new Person[size];
}
};
//由于book是另一个可序列化对象,所以它的反序列化过程需要传递当前线程的上下文类加载器,否则会报无法找到类的错误
private Person(Parcel in){
userId =in.readInt();
userName=in.readString();
isMan=in.readInt()==1;
son=in.readParcelable(Thread.currentThread().getContentClassLoader());
}
下面为一个例子
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
public class Person implements Parcelable{
public String name ;
public int age ;
public String[] msg ;
public int garde ;
public Son son ;
private boolean isMan;
@Override
public int describeContents() {
Log.v("Tag", " describeContents ");
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
Log.v("Tag", this+" ------> writeToParcel "+flags);
//这里是把对象的字段一个一个写到流里面,写的顺序要和下面读的顺序一摸一样
dest.writeInt(age);
dest.writeString(name);
//这几句话是写数组的,因为数组的长度不确定,所以先确定数组长度,如果为空就不写,但是要把0 给发过去
//让下面的好判断能不能读数组,也就是说下面如果读到的长度是0,那么就不读数组了,否则就创建相同长度的数组去读
if(msg==null){
dest.writeInt(0);
}else{
dest.writeInt(msg.length);
}
//如果数组为空,就可以不写
if(msg!=null){
dest.writeStringArray(msg);
}
dest.writeInt(garde);
dest.writeParcelable(son, flags);
dest.writeInt(isMan?1:-1);//是 就传递1,否则传递-1
}
public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
@Override
public Person[] newArray(int size) {
Log.w("Tag", " person new Array : "+size);
return new Person[size];
}
@Override
public Person createFromParcel(Parcel source) {
return new Person(source) ;
}
};
private Person(Parcel source){
//开始读对象的流顺序要和上面写的一样
Log.w("Tag", " createFromParcel ");
age = source.readInt();
name = source.readString() ;
//开始读数组的长度
int length = source.readInt() ;
Log.v("Tag", " length : "+length);
String[] msg = null ;
//如果数组长度大于0,那么就读数组, 所有数组的操作都可以这样。
if(length>0){
msg = new String[length];
source.readStringArray(msg);
}
grade = source.readInt() ;
son = source.readParcelable(Son.class.getClassLoader());
Log.i("Tag", " son : "+son);
isMan = source.readInt()>0?true:false;
}
}
序列化Bitmap:
1. 可以将Bitmap 转成 byte【】数组,然后在转换成 bitmap;
2.但是Bitmap 时已经是序列化好的了,所以可以当成 Son 进行传递;
public byte[] getBytes(Bitmap bitmap){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 0, baos);
return baos.toByteArray();
}
public Bitmap getBitmap(byte[] data){
return BitmapFactory.decodeByteArray(data, 0, data.length);
}
package com.redoor.rcs.info;
import java.io.ByteArrayOutputStream;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Parcel;
import android.os.Parcelable;
/**
* @version 1.0
*
* @author DongXiang
*
* @action 消息列表界面,展示的条item对象;
* <br>目前支持:单聊消息对象,
* <br>群聊,公众账号,稍后会陆续兼容;
*
* @time 2017年4月7日下午2:35:27
*
*/
public class MsgListInfo implements Parcelable{
/** 消息类型:0 = 一对一消息;1 = 公账号消息;2 = 群聊消息*/
private int msgType;
/** 聊天展示的*/
private String title;
/** <br> 1.单聊:单聊对象手机号
* <br> 2.群聊:群聊的房间号
* <br> 3.公众账号:公众账号的房间号
*/
private String chatRoomID;
/** 最后一条消息,内容*/
private String lastMsgContent;
/** 是否显示警告*/
private boolean isShowWarning;
/** 这三个参数,供备用:像 handler 的 Message 的参数一样*/
private String param1;
/** 这三个参数,供备用:像 handler 的 Message 的参数一样*/
private String param2;
/** 这三个参数,供备用:像 handler 的 Message 的参数一样*/
private String param3;
/** 最后互撩消息的 时间,long类型;排序使用的*/
private long dateLong;
/** 最后互撩消息的 时间,String类型;显示使用*/
private String dateStr;
/** 未读消息的条数 */
private int unReadNum;
/** 头像的图标:bitmap已经 实现了序列化Parcelable*/
private Bitmap headBitmap;
public MsgListInfo(int msgType, String title, String chatRoomID,
String lastMsgContent, boolean isShowWarning, String param1,
String param2, String param3, long date, String dateStr,
int unReadNum, Bitmap headBitmap) {
super();
this.msgType = msgType;
this.title = title;
this.chatRoomID = chatRoomID;
this.lastMsgContent = lastMsgContent;
this.isShowWarning = isShowWarning;
this.param1 = param1;
this.param2 = param2;
this.param3 = param3;
this.dateLong = date;
this.dateStr = dateStr;
this.unReadNum = unReadNum;
this.headBitmap = headBitmap;
}
public MsgListInfo() {
super();
}
//===============================================
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(msgType);
dest.writeString(title);
dest.writeString(chatRoomID);
dest.writeString(lastMsgContent);
dest.writeInt(isShowWarning?1:-1);//展示就传递过去1,否则传递过去-1;
dest.writeString(param1);
dest.writeString(param2);
dest.writeString(param3);
dest.writeLong(dateLong);
dest.writeString(dateStr);
dest.writeInt(unReadNum);
int len=0;
if (headBitmap==null) {
dest.writeInt(len);//判断bitmap 是否为空,若为空则
}else {
byte[] bitmapBytes=getBytes(headBitmap);
len=bitmapBytes.length;
dest.writeInt(len);
dest.writeByteArray(bitmapBytes);
}
}
private MsgListInfo(Parcel source) {
msgType=source.readInt();
title=source.readString();
chatRoomID=source.readString();
lastMsgContent=source.readString();
isShowWarning=source.readInt()>0?true:false;
param1=source.readString();
param2=source.readString();
param3=source.readString();
dateLong=source.readLong();
dateStr=source.readString();
unReadNum=source.readInt();
int len=source.readInt();
if (len<=0) {
headBitmap=null;
}else {
byte[] bitmapBytes=new byte[len];
source.readByteArray(bitmapBytes);
headBitmap=getBitmap(bitmapBytes);
}
}
public static final Parcelable.Creator<MsgListInfo> CREATOR=new Parcelable.Creator<MsgListInfo>() {
@Override
public MsgListInfo createFromParcel(Parcel source) {
// TODO Auto-generated method stub
return new MsgListInfo(source);
}
@Override
public MsgListInfo[] newArray(int size) {
// TODO Auto-generated method stub
return new MsgListInfo[size];
}
};
private byte[] getBytes(Bitmap bitmap){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
return baos.toByteArray();
}
private Bitmap getBitmap(byte[] data){
return BitmapFactory.decodeByteArray(data, 0, data.length);
}
}
扩展:
本地File 和 Bitmap 进行转化:
public void saveInputTypeEditTextDataToFile(Object object,String fileName){
ObjectOutputStream objectOutputStream = null;
try {
FileOutputStream fileOutputStream = mContext.openFileOutput(fileName,Context.MODE_PRIVATE);
objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(object);
objectOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}finally{
if (objectOutputStream != null) {
try {
objectOutputStream.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public byte[] readBitmapDataFromFile(String fileName){
ObjectInputStream objectInputStream = null;
try {
FileInputStream fileInputStream = mContext.openFileInput(fileName);
objectInputStream = new ObjectInputStream(fileInputStream);
byte[] editTexts = (byte[]) objectInputStream.readObject();
return editTexts;
} catch (StreamCorruptedException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}finally{
if (objectInputStream != null) {
try {
objectInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
Tips:
一、序列化的知识点:
所谓序列化其实就是为了保存在内存中的各种对象的状态,并且可以把保存的对象状态再读出来的一种保存对象状态的机制。
二、需要序列化的情况:
1、当想把内存中的对象保存到一个文件中或者数据库中的时候;
2、当想通过RMI传输对象的时候;
3、当想用套接字在网络上传送对象时。
在没有序列化前,每个保存在Heap中的对象都有相应的状态,即实例变量,当对象序列化后,就可以将类的类型、属性的值等
相应信息被保存到***.ser文件中,这样以后就可以将它从文件中读出来,从新在Heap中创建原来的对象。
仨、对象序列化的注意事项:
1、当一个父类实现序列化,子类自动实现序列化,无需再次实现Serializable接口;
2、当一个对象的实例变量引用其他对象,序列化该对象时也会将引用对象进行序列化;
3、并非所有的对象都可以序列化(可在度娘上找到)