数据持久化就是指将内存中的瞬时数据保存到存储设备中,保证即使设备在重启之后,数据仍然不会丢失。 持久化技术提供了一种机制可以让数据在瞬时状态和持久状态之间进行转换。
Android系统主要提供了三种方式用于实现数据持久化功能:文件存储、SharedPreference存储、以及数据库存储。
一、文件存储
文件存储比较适合用于存储一些简单的文本数据或二进制数据,因为它不会对存储内容进行任何处理, 只是原封不动地保存到文件当中。
文件存储的方式概括来说就是利用Java流的方式将数据写入到文件中存储。
下面来写一个小例子:
首先在mainLayout中添加一个EditText,用于输入数据:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<EditText
android:id="@+id/edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Information"/>
</LinearLayout>
然后实现一个save()方法,用于存储数据:(利用输出流将数据保存到文件中)
public void save(String inputText) {
FileOutputStream out = null;
BufferedWriter writer = null;
try {
out = openFileOutput("data", Context.MODE_PRIVATE);
writer = new BufferedWriter(new OutputStreamWriter(out));
writer.write(inputText);
writer.close();
} catch (FileNotFoundException e) {
System.out.println("找不到文件");
} catch (IOException e) {
e.printStackTrace();
}
}
Context类提供了一个返回FileOutputStream对象的openFileOutput()方法。openFileOutput()方法 接收两个参数,第一个参数是文件名(不包含路径,所有文件都默认存储到/data/data/<package name>/files/目录下),用于存储数据的文件就是用的这个名字;第二个参数是文件的操作模式。文件的操作模式主要有两种可选, 分别是MODE_PRIVATE和MODE_APPEND。其中MODE_PRIVATE是默认的操作模式,表示当指定同样文件名的时候,所写入的内容将会覆盖原文件中的内容,而MODE_APPEND则表示如果文件已存在,就往文件中追加内容。 (文件的操作模式原本还有两外两种:MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE,分别表示允许 其他应用程序对我们程序中的文件进行读写操作,由于这两种模式容易引起安全性漏洞,所以在Android4.2 中已被废弃)
然后实现load()方法用于取出文件中的数据:(利用输出流将文件中的数据还原到EditText中)
public String load() {
FileInputStream in = null;
BufferedReader reader = null;
StringBuilder content = new StringBuilder();
try {
in = openFileInput("data");
reader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = reader.readLine()) != null) {
content.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return content.toString();
}
Context类中还提供了一个与openFileOutput()方法对应的openFileInput()方法,openFileInput()方法接收一个 文件名 的参数(对应openFileOutput()方法中的第一个文件名参数),然后会默认到/data/data/<package name>/files/目录下加载这个文件,最终返回FileInputStream对象。
load()方法首先通过openFileInput()方法获取到FileInputStream对象,然后通过FileInputStream对象创建InputStreamReader对象再创建BufferedReader对象。最后通过BufferedReader对象的readLine()方法对读取数据文件,并将数据存入到StringBuilder中。最后load()方法返回StringBuilder对象转换的String。
完整例子:MainActivity
public class MainActivity extends AppCompatActivity {
private EditText edit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edit = (EditText) findViewById(R.id.edit);
String inputText = load();
if (!TextUtils.isEmpty(inputText)) { //创建Activity时如果有存储数据则读取并恢复数据
edit.setText(inputText);
edit.setSelection(inputText.length()); //设置光标位置到末尾
Toast.makeText(this, "Restoring succeeded", Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
String inputText = edit.getText().toString();
if (!TextUtils.isEmpty(inputText)){
save(inputText); //在销毁时储存数据
}
}
public void save(String inputText) { //储存数据
FileOutputStream out = null;
BufferedWriter writer = null;
try {
out = openFileOutput("data", Context.MODE_PRIVATE);
writer = new BufferedWriter(new OutputStreamWriter(out));
writer.write(inputText);
writer.close();
} catch (FileNotFoundException e) {
System.out.println("找不到文件");
} catch (IOException e) {
e.printStackTrace();
}
}
public String load() { //读取数据
FileInputStream in = null;
BufferedReader reader = null;
StringBuilder content = new StringBuilder();
try {
in = openFileInput("data");
reader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = reader.readLine()) != null) {
content.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return content.toString();
}
}
这个程序的大概思路是:在创建Activity的时候先调用load()方法判断是否有存储数据,有的话对EditText进行数据恢复并弹出Toast进行提示。然后在Activity销毁的时候判断若EditText中内容不为空则调用save()方法进行数据存储。
注:TextUtils.isEmpty()方法在传入的字符串为null或为空字符串的时候均会返回true。