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 Student student = new Student("白文磊" , 25 ); Gson gson = new Gson(); String jsonString = gson.toJson(student); Log.i(TAG, "onCreate: " + jsonString); 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()); 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); Student[] students; students = gson.fromJson(jsonString, Student[].class); Log.i(TAG, "onCreate: " + students.length);