扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
本文中介绍三种Android中常见的序列化的使用
序列化是把对象以二进制的形式写入硬盘或者文件中,这样对象就能存入数据库、文件中或者在网络上进行传输。
反序列化是把二进制的对象数据读取出来并还原成对象的过程,这个对象的数据和序列化之前是一样的。
使用Serializable使用Serializable方式进行序列化,需要让要序列化的对象implements Serializable
接口。
serialVersionUID:建议主动生成一个固定的序列号。Idea或者AS中可以通过系统设置,让系统自己生成这个ID,setting—>Inspections->输入关键词UID->Serializable class...
,然后在代码中,点击点击类名:Alt+Enter
,就能生成UID.
如果不主动为这个字段设值,java会以这个对象中的属性为这个字段计算一个serialVersionUID。所以如果当前对象的类中新增一个属性,那么serialVersionUID就会改变,这会导致因为serialVersionUID不一致而造成的反序列化失败。
public class Student implements Serializable {private static final long serialVersionUID = 2894055642774362458L;
private transient String name;
@Expose(serialize = false,deserialize = true)
private int age;
@SerializedName("goals")
private Score score;
public Student(){}
public Student(String name, int age, Score score) {this.name = name;
this.age = age;
this.score = score;
}
public String getName() {return name;
}
public int getAge() {return age;
}
public Score getScore() {return score;
}
public void setName(String name) {this.name = name;
}
public void setAge(int age) {this.age = age;
}
public void setScore(Score score) {this.score = score;
}
@Override
public String toString() {return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
public class Score implements Serializable {private static final long serialVersionUID = -1947844853731260432L;
private int math;
private int english;
private int chinese;
public int getMath() {return math;
}
public void setMath(int math) {this.math = math;
}
public int getEnglish() {return english;
}
public void setEnglish(int english) {this.english = english;
}
public int getChinese() {return chinese;
}
public void setChinese(int chinese) {this.chinese = chinese;
}
public Score() {}
public Score(int math, int english, int chinese) {this.math = math;
this.english = english;
this.chinese = chinese;
}
@Override
public String toString() {return "Score{" +
"math=" + math +
", english=" + english +
", chinese=" + chinese +
'}';
}
}
序列化使用ObjectOutPutStream类实现对象的序列化。
new ObjectOutputStream(OutputStream output)
,安卓中可以使用openFileOutput(filepath)
打开OutputStream流writeObject(obj)
:obj是实现Serializable接口的实体类对象Student serialStudent = new Student("花",18,new Score(98,95,95));
ObjectOutputStream output = new ObjectOutputStream(openFileInput("student.txt"));
output.writeObject(obj);
output.close();
反序列化使用ObjectOutPutStream类实现对象的序列化。
new ObjectInputStream(InputStream input)
,安卓中可以使用openFileInput(filepath)
打开InputStream流readObject
():把二进制的对象数据进行返序列化ObjectInputStream input = new ObjectInputStream(openFileInput("student.txt"));
Student serialStudent1 = (Student) input.readObject();
input.close();
完整实现//Serializable test:生成的 文件是16进制类型的,如果想要看文件,可以在AS中安装插件进行查看
Student serialStudent = new Student("花",18,new Score(98,95,95));
try {ObjectOutputStream output = new ObjectOutputStream(openFileOutput("student.txt",MODE_PRIVATE));
output.writeObject(serialStudent);
output.flush();
output.close();
ObjectInputStream input = new ObjectInputStream(openFileInput("student.txt"));
Student serialStudent1 = (Student) input.readObject();
input.close();
Log.i(TAG, "onCreate: Serializable_test"+serialStudent1.toString());
} catch (IOException | ClassNotFoundException e) {e.printStackTrace();
}
使用Parcelable使用Parcelable方式进行序列化,需要让要序列化的对象implements Parcelable
接口,创建,并且实现它内部的方法。
public class StudentP implements Parcelable {private String name;
private int age;
private ScoreP score;
public StudentP(){}
public StudentP(String name, int age, ScoreP score) {this.name = name;
this.age = age;
this.score = score;
}
protected StudentP(Parcel in) {name = in.readString();
age = in.readInt();
}
public static final CreatorCREATOR = new Creator() {@Override
public StudentP createFromParcel(Parcel in) {return new StudentP(in);
}
@Override
public StudentP[] newArray(int size) {return new StudentP[size];
}
};
public String getName() {return name;
}
public int getAge() {return age;
}
public ScoreP getScore() {return score;
}
public void setName(String name) {this.name = name;
}
public void setAge(int age) {this.age = age;
}
public void setScore(ScoreP score) {this.score = score;
}
@Override
public int describeContents() {return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {dest.writeString(name);
dest.writeInt(age);
}
@Override
public String toString() {return "StudentP{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
public class ScoreP implements Parcelable {private int math;
private int english;
private int chinese;
protected ScoreP(Parcel in) {math = in.readInt();
english = in.readInt();
chinese = in.readInt();
}
@Override
public void writeToParcel(Parcel dest, int flags) {dest.writeInt(math);
dest.writeInt(english);
dest.writeInt(chinese);
}
@Override
public int describeContents() {return 0;
}
public static final CreatorCREATOR = new Creator() {@Override
public ScoreP createFromParcel(Parcel in) {return new ScoreP(in);
}
@Override
public ScoreP[] newArray(int size) {return new ScoreP[size];
}
};
public int getMath() {return math;
}
public void setMath(int math) {this.math = math;
}
public int getEnglish() {return english;
}
public void setEnglish(int english) {this.english = english;
}
public int getChinese() {return chinese;
}
public void setChinese(int chinese) {this.chinese = chinese;
}
public ScoreP() {}
public ScoreP(int math, int english, int chinese) {this.math = math;
this.english = english;
this.chinese = chinese;
}
@Override
public String toString() {return "ScoreP{" +
"math=" + math +
", english=" + english +
", chinese=" + chinese +
'}';
}
}
序列化@Override
public void writeToParcel(Parcel dest, int flags) {dest.writeInt(math);
dest.writeInt(english);
dest.writeInt(chinese);
}
反序列化protected ScoreP(Parcel in) {math = in.readInt();
english = in.readInt();
chinese = in.readInt();
}
注意:
序列化和反序列化时的顺序必须一致。比如下面这几个属性的顺序是int,String,int类型的 ,那么它的序列化和反序列化就得按照顺序writeInt和readInt,如下:
//属性顺序
private int math;
private String name ;
private int english;
//序列化顺序
public void writeToParcel(Parcel dest, int flags) {dest.writeInt(math);
dest.writeString(name);
dest.writeInt(chinese);
}
//反序列化顺序
protected T(Parcel in) {math = in.readInt();
english = in.readString();
chinese = in.readInt();
}
完整实现Parcelable是专门为Android定制的序列化方式,它不像Serializable方式那样频繁的操作IO,所以它的效率高很多。
//Parcelable test
Intent intent = new Intent(this , ParcelableActivity.class);
StudentP parcelableStudent = new StudentP("MAY", 17, new ScoreP(95, 90, 90));
Bundle bundle = new Bundle();
bundle.putParcelable("student",parcelableStudent);
intent.putExtra("student",bundle);
startActivity(intent);
使用JsonJSON(JavaScript Object Notation, JS对象简谱)是一种轻量级的数据交换格式。它的层次结构简洁清晰,是网络上传输数据很好用的一个手段。Json有几个很好用的库,FastJson和Gson,本文使用Gson。
编写和校验Json串beJson
网站:www.beJson.comGson地址:https://github.com/google/gson
dependencies {
implementation 'com.google.code.gson:gson:2.10'
}
序列化使用Gson的toJson(obj)
方法.
//object
Gson gson = new Gson();
Student student = new Student("teresa_may",16,new Score(60,60,60));
String stuJson = gson.toJson(student);
Log.i(TAG, "onCreate: gson_stu:"+stuJson);
Student[] students = new Student[5];
for (int i = 0;i<5;i++){Student s = new Student("teresa_may",16+i,new Score(60+i,60+i,60+i));
students[i] = s;
}
String stus_Json = gson.toJson(students);
Log.i(TAG, "onCreate: stu_array_json:"+stus_Json);
//list、map、set
Liststu_list = new ArrayList(Arrays.asList(students));
String stulist_Json = gson.toJson(stu_list);
Log.i(TAG, "onCreate: stus_list_json:"+stus_Json);
反序列化使用Gson的fromJson(json_str,Class)方法。
Student student_f = gson.fromJson(stuJson,Student.class);
Log.i(TAG, "onCreate: gson_from_json:"+student_f.toString());
Student[] students_f = gson.fromJson(stus_Json,Student[].class);
Log.i(TAG, "onCreate: students_from_json:"+students_f.toString());
略有不同。需要使用Type对ArrayList的参数化类型进行明确才能进行反序列化。
Type type = new TypeToken>(){}.getType();
ArrayListstudents_list = gson.fromJson(stulist_Json,type);
Log.i(TAG, "onCreate: students_list from json:"+students_list.toString());
完整实现 //Gson test
//object
Gson gson = new Gson();
Student student = new Student("teresa_may",16,new Score(60,60,60));
String stuJson = gson.toJson(student);
Log.i(TAG, "onCreate: gson_stu:"+stuJson);
Student student_f = gson.fromJson(stuJson,Student.class);
Log.i(TAG, "onCreate: gson_from_json:"+student_f.toString());
//array
Student[] students = new Student[5];
for (int i = 0;i<5;i++){Student s = new Student("teresa_may",16+i,new Score(60+i,60+i,60+i));
students[i] = s;
}
String stus_Json = gson.toJson(students);
Log.i(TAG, "onCreate: stu_array_json:"+stus_Json);
Student[] students_f = gson.fromJson(stus_Json,Student[].class);
Log.i(TAG, "onCreate: students_from_json:"+students_f.toString());
//list、map、set
Liststu_list = new ArrayList(Arrays.asList(students));
String stulist_Json = gson.toJson(stu_list);
Log.i(TAG, "onCreate: stus_list_json:"+stus_Json);
Type type = new TypeToken>(){}.getType();
ArrayListstudents_list = gson.fromJson(stulist_Json,type);
Log.i(TAG, "onCreate: students_list from json:"+students_list.toString());
控制序列化和反序列化
@Serialization用于属性上表示该属性在json中的key值,如果不使用这个注解,那么在序列化和反序列化的时候使用属性的名字作为key。有时候json串中的key存在java中的关键字时,可以使用这个注解为当前属性和json串中的key进行映射。
@SreializedName("class")
private String cls;
json中的样子:
{"class":"Student.class"}
@Expose@Expose控制对象的序列化和反序列化,有两个属性:serialize
和deserialize
,默认值为true,表示允许序列化和反序列化。
@Expose(serialize = false,deserialize = true)//字段不参与序列化,允许反序列化
static关键字static关键字修饰的字段不会被序列化,反序列化时内部的值是该字段类型的默认值。
transient关键字static关键字修饰的字段不会被序列化和反序列化
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流