0%

Android 中对象序列化方法

Android 中对象序列化方法—Serializable Parcelable Json

如何将在两个进程 或者 两个活动中传递对象、如何将一个对象存储到磁盘当中,以Student为例

Serializable

1. 将对象实现 Serializable 接口

​ 该接口中并没有抽象方法,所以不需要我们重写

​ 这里需要注意的是 我们在类的内部显式定义了一个serialVersionUID对象 ,这不是必须的,因为SDK内部会帮你自动生成一个uid来标识该对象。但是,一旦你修改了该类的属性(增加或者删除)SDK认为这是一个新的类,赋予一个新的uid,导致之前存储下来的对象无法与现在的新类匹配上。保险起见 :加上比较稳妥.

​ Serializable 默认将所有属性都序列化为二进制文件,如果某个属性不序列化,在属性名前 加入修饰 transient

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
public class Student implements Serializable {
private static final long serialVersionUID = -1881552733054514966L;
private String name;
private int age;
private Score score;

public Student(String name, int age, Score score) {
this.name = name;
this.age = age;
this.score = score;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public Score getScore() {
return score;
}

public void setScore(Score score) {
this.score = score;
}
}

class Score implements Serializable {
private static final long serialVersionUID = 1522948871618988346L;
private int math;
private int chinese;
private int english;
private String grade;

public Score(int math, int chinese, int english) {
this.math = math;
this.chinese = chinese;
this.english = english;
if (this.math >= 90 && this.chinese >= 90 && this.english >= 90) {
this.grade = "A";
} else if (this.math >= 80 && this.chinese >= 80 && this.english >= 80) {
this.grade = "B";
} else {
this.grade = "C";
}
}

public int getMath() {
return math;
}

public void setMath(int math) {
this.math = math;
}

public int getChinese() {
return chinese;
}

public void setChinese(int chinese) {
this.chinese = chinese;
}

public int getEnglish() {
return english;
}

public void setEnglish(int english) {
this.english = english;
}

public String getGrade() {
return grade;
}

public void setGrade(String grade) {
this.grade = grade;
}
}
2. 将对象存储到磁盘当中

通过ObjectOutputStream . writeObject 以及openFileOutput()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
String name = editTextName.getText().toString();
int age = Integer.parseInt(editTextAge.getText().toString());
int math = Integer.parseInt(editTextMath.getText().toString());
int chinese = Integer.parseInt(editTextChinese.getText().toString());
int english = Integer.parseInt(editTextEnglish.getText().toString());
Score score = new Score(math, chinese, english);
Student student = new Student(name, age, score);
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(openFileOutput(FILE_NAME, MODE_PRIVATE));
objectOutputStream.writeObject(student);
objectOutputStream.flush();
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
3.从磁盘中读取对象

通过ObjectInputStream.readObject() 以及 openFileInput

1
2
3
4
5
6
7
8
9
10
11
12
13
try {
ObjectInputStream objectInputStream = new ObjectInputStream(openFileInput(FILE_NAME));
Student student = (Student) objectInputStream.readObject();
Score score = student.getScore();
editTextMath.setText(String.valueOf(score.getMath()));
editTextChinese.setText(String.valueOf(score.getChinese()));
editTextEnglish.setText(String.valueOf(score.getEnglish()));
txtGrade.setText(score.getGrade());
editTextName.setText(student.getName());
editTextAge.setText(String.valueOf(student.getAge()));
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}

Parceable

​ 在讲Parceable 如何序列化 对象之前 ,首先说一下安卓应用程序中进程的问题。一般来说 一个应用程序就是一个进程,但不意味着一个应用程序只能有一个进程,我们可以在AndroidMnifest清单文件中 对Activity的process起另一个名字,就会导致多了一个进程

​ 如何在两个活动之间传递一个对象,一个简单粗暴的方法就是通过Application中间件来 (类似于邮箱)活动A将对象赋值到Application中的对象,活动B再从Application中取回,但是这种方法只能在同一个进程中传递,在不同进程中就无法传递对象了(Parceable可以)

1. 将对象实现Parceable 接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
public class Student implements Parcelable {
private String name;
private int age;
private Score score;

public Student(String name, int age, Score score) {
this.name = name;
this.age = age;
this.score = score;
}

protected Student(Parcel in) {
name = in.readString();
age = in.readInt();
score = in.readParcelable(Score.class.getClassLoader());
}

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
dest.writeParcelable(score, flags);
}

@Override
public int describeContents() {
return 0;
}

public static final Creator<Student> CREATOR = new Creator<Student>() {
@Override
public Student createFromParcel(Parcel in) {
return new Student(in);
}

@Override
public Student[] newArray(int size) {
return new Student[size];
}
};

public Score getScore() {
return score;
}

public void setScore(Score score) {
this.score = score;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}


class Score implements Parcelable {
private int math;
private int chinese;

public Score(int math, int chinese) {
this.math = math;
this.chinese = chinese;
}

protected Score(Parcel in) {
math = in.readInt();
chinese = in.readInt();
}

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(math);
dest.writeInt(chinese);
}

@Override
public int describeContents() {
return 0;
}

public static final Creator<Score> CREATOR = new Creator<Score>() {
@Override
public Score createFromParcel(Parcel in) {
return new Score(in);
}

@Override
public Score[] newArray(int size) {
return new Score[size];
}
};

public int getMath() {
return math;
}

public void setMath(int math) {
this.math = math;
}

public int getChinese() {
return chinese;
}

public void setChinese(int chinese) {
this.chinese = chinese;
}
}
2.将对象传递到下一个活动中

通过 Intent中的 putExtra()方法,将序列化的对象传递出去

1
2
3
4
5
6
7
8
9
10
11
12
public void onClick(View v) {
String name = binding.editName.getText().toString();
int age = Integer.parseInt(binding.editAge.getText().toString());
int Chinese = Integer.parseInt(binding.editChinese.getText().toString());
int Math = Integer.parseInt(binding.editMath.getText().toString());

Score score = new Score(Math, Chinese);
Student student = new Student(name, age, score);
Intent intent = new Intent(MainActivity.this, MainActivity2.class);
intent.putExtra("student", student);
startActivity(intent);
}
3.活动解析数据

通过getIntent.getParcelableExtra()方法 获得活动传递过来的对象

1
2
3
4
5
6
ActivityMain2Binding binding = DataBindingUtil.setContentView(this, R.layout.activity_main2);
Student student = getIntent().getParcelableExtra("student");
binding.textViewName.setText(student.getName());
binding.textViewAge.setText(String.valueOf(student.getAge()));
binding.textViewChinese.setText(String.valueOf(student.getScore().getChinese()));
binding.textViewMath.setText(String.valueOf(student.getScore().getMath()));

Json

1.添加GSON依赖
1
2
//GSOn依赖
implementation 'com.google.code.gson:gson:2.8.6'
2.序列化与反序列化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//1.将对象序列化
Student student = new Student("白文磊", 25);
Gson gson = new Gson();
String jsonString = gson.toJson(student);
Log.i(TAG, "onCreate: " + jsonString);

//2. 反序列化
String ReverseJson = "{\"name\": \"bai\", \"age\": 16}";
Student student1 = gson.fromJson(ReverseJson, Student.class);
Log.i(TAG, "onCreate: " + student1.getName());
Log.i(TAG, "onCreate: " + student1.getAge());

//3. 将多个对象序列化
Student one = new Student("one", 1);
Student two = new Student("two", 2);
Student[] arr = new Student[]{one, two};
jsonString = gson.toJson(arr);
Log.i(TAG, "onCreate: " + jsonString);

//4. 将序列化组 反序列化
Student[] students;
students = gson.fromJson(jsonString, Student[].class);
Log.i(TAG, "onCreate: " + students.length);