什么是序列化
借用百度百科的一句话,序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
简单说就是将对象中所有字段信息以某种形式保存到磁盘中,这个过程称之为序列化,反序列化也就是把某种形式的数据根据规则转换成对象。
下面介绍几种我所使用过的方案。
一、Serializable
这是Java中自带的一个序列化方案,同样Android中也可以使用,使用很简单,也是比较广泛的,另外要序列化的对象一定要实现Serializable接口,序列化过程中会使用serialVersionUID的版本号和序列化的类相关联,在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。public class Infos implements Serializable{
private static final long serialVersionUID = 1L;
private String mName;
private Long mTimer;
public String getmName(){
return mName;
}
public void setmName(String mName){
this.mName = mName;
}
public Long getmTimer(){
return mTimer;
}
public void setmTimer(Long mTimer){
this.mTimer = mTimer;
}
}public class MainActivity extends AppCompatActivity{
private TextView mInfoTv;
private EditText mEtView;
private String path = Environment.getExternalStorageDirectory().getPath()+"/info.data";
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mInfoTv =findViewById(R.id.tv_info);
mEtView=findViewById(R.id.et_info);
}
/**
* 读取
*/
public void readInfo(){
try {
/**
* 如果文件存在
*/
if (new File(path).exists()){
/**
* 通过ObjectInputStream读取对象
*/
ObjectInputStream objectInputStream =new ObjectInputStream(new FileInputStream(path));
Infos infos =(Infos) objectInputStream.readObject();
mInfoTv.setText("名称"+infos.getmName()+"\n\r"+"时间:"+ infos.getmTimer());
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 保存
* @param view
*/
public void onSaveClick(View view){
/**
* 设置对象各个字段值
*/
Infos infos =new Infos();
infos.setmName(mEtView.getText().toString());
infos.setmTimer(System.currentTimeMillis());
/**
* 通过ObjectOutputStream将对象序列化到本地
*/
try {
ObjectOutputStream objectOutputStream =new ObjectOutputStream(new FileOutputStream(path));
objectOutputStream.writeObject(infos);
objectOutputStream.flush();
objectOutputStream.close();
readInfo();
} catch (IOException e) {
e.printStackTrace();
}
}
}<?xml version="1.0" encoding="utf-8"?>
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
tools:context=".MainActivity">
android:id="@+id/et_info"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:onClick="onSaveClick"
android:text="保存"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:id="@+id/tv_info"
android:text=""
android:layout_width="match_parent"
android:layout_height="wrap_content">
当我们输入数据,点击保存,就可以看到信息。
二、Parcelable
Parcelable是Android为我们提供的序列化的接口,Parcelable相对于Serializable的使用相对复杂一些,但是Parcelable不能使用在要将数据存储在磁盘上的情况下,他是基于内存的,我们在跨进程对象传递一般使用Parcelable。
编写Parcelable需要大量模板代码,所以可是使用一个工具,也就是下面这个。之后Alt+Insert点击Parcelable就可以生成如下代码。describeContents返回当前对象的内容描述,一般0即可。
writeToParcel将当前的对象写入Parcel容器中。
createFromParcel反序列化的方法,将Parcel还原成java对象。
newArray创建Parcelable类的新数组。其中每个条目都初始化为空。供外部类反序列化本类数组使用。public class Infos implements Parcelable{
private static final long serialVersionUID = 1L;
private String mName;
private Long mTimer;
public String getmName(){
return mName;
}
public void setmName(String mName){
this.mName = mName;
}
public Long getmTimer(){
return mTimer;
}
public void setmTimer(Long mTimer){
this.mTimer = mTimer;
}
@Override
public int describeContents(){
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags){
dest.writeString(this.mName);
dest.writeValue(this.mTimer);
}
public Infos(){
}
protected Infos(Parcel in){
this.mName = in.readString();
this.mTimer = (Long) in.readValue(Long.class.getClassLoader());
}
public static final Creator CREATOR = new Creator() {
@Override
public Infos createFromParcel(Parcel source){
return new Infos(source);
}
@Override
public Infos[] newArray(int size) {
return new Infos[size];
}
};
}
之后我们就可以这样使用。public void onSaveClick(View view){
Infos infos =new Infos();
infos.setmName(mEtView.getText().toString());
infos.setmTimer(System.currentTimeMillis());
Intent intent =new Intent(this,TestActivity.class);
intent.putExtra("info",infos);
startActivity(intent);
}
三、SQLiteDatabase
SQLiteDatabase是Android提供的用来管理Sqlite database的一种数据持久化解决方案。SQLiteDatabase提供了基本的增删改查方法,可以执行SQL命令,执行其他常见数据库管理任务的方法。Sqlite主要用来存储复杂的关系型数据,Android原生提供的操作API 不太好用,需要我们编写很多样板代码,还容易出错,所以现在有很多封装Sqlite的ORM框架,下面介绍一个简单易用的litepal。
首先引入依赖implementation 'org.litepal.guolindev:core:3.1.1'
之后我们在assets下创建配置文件litepal.xml。配置文件详细查看Github地址:https://github.com/LitePalFramework/LitePal。<?xml version="1.0" encoding="utf-8"?>
要注意的是,要存储的对象要继承LitePalSupport。LitePalSupport中定义的save方法用于将对象存储,或者update方法进行更新。这其中原理也是通过反射获取字段值。public class Infos extends LitePalSupport{
private String mName;
private Long mTimer;
public String getmName(){
return mName;
}
public void setmName(String mName){
this.mName = mName;
}
public Long getmTimer(){
return mTimer;
}
public void setmTimer(Long mTimer){
this.mTimer = mTimer;
}
}public class MainActivity extends AppCompatActivity{
private TextView mInfoTv;
private EditText mEtView;
private String path = Environment.getExternalStorageDirectory().getPath()+"/info.data";
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mInfoTv =findViewById(R.id.tv_info);
mEtView=findViewById(R.id.et_info);
readInfo();
}
/**
* 读取
*/
public void readInfo(){
mInfoTv.setText("");
List all = LitePal.findAll(Infos.class);
StringBuffer stringBuffer =new StringBuffer();
Log.i("TAG", "readInfo: "+all.size());
for (Infos infos : all) {
stringBuffer.append("姓名:"+infos.getmName());
stringBuffer.append("\n\r");
stringBuffer.append("时间:"+infos.getmTimer());
stringBuffer.append("\n\r");
}
mInfoTv.setText(stringBuffer.toString());
}
/**
* 保存
* @param view
*/
public void onSaveClick(View view){
Infos infos =new Infos();
infos.setmName(mEtView.getText().toString());
infos.setmTimer(System.currentTimeMillis());
infos.save();
readInfo();
}
}
在这里插入图片描述
四、SharedPreferences
SharedPreferences是Android平台上一个轻量级的存储类,使用非常简单,他向HashMap一样,以键值对的方式存储在文件中,经常用来保存应用的一些常用配置。
最终这个文件会存在data/data//shared_prefs目录下,会生成了一个xml文件。正常情况下,其他APP是无法访问这个目录的,但是在ROOT后,这个目录就可以随便看,如果要保存敏感的信息,最好是加密。
当我们通过Editor存入数据时,一定要记得commit或apply进行提交,否则不会保存。public class MainActivity extends AppCompatActivity{
private TextView mInfoTv;
private EditText mEtView;
private String path = Environment.getExternalStorageDirectory().getPath()+"/info.data";
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mInfoTv =findViewById(R.id.tv_info);
mEtView=findViewById(R.id.et_info);
readInfo();
}
/**
* 读取
*/
public void readInfo(){
mInfoTv.setText(getSharedPreferences("data",Context.MODE_PRIVATE).getString("name",""));
}
/**
* 保存
* @param view
*/
public void onSaveClick(View view){
SharedPreferences sharedPreferences =getSharedPreferences("data", Context.MODE_PRIVATE);
SharedPreferences.Editor edit = sharedPreferences.edit();
edit.putString("name",mEtView.getText().toString());
edit.commit();
readInfo();
}
}
五、JSON
JSON的全程叫JavaScript Object Notation,是一种轻量级的数据交换格式,目前大部分网络传输时候数据格式都是以JSON存在,当然也有xml格式的。
至于他的格式,这里就不说了,在说说他的几种框架。FastJson(阿里巴巴)、GSON(谷歌)、org.json。
阿里巴巴的FastJson最近爆出很多漏洞,具体是什么没有太了解,网上又是铺天盖地的再见FastJson的文章,至于怎么选择,要看自己喽。