Android持久化技术(一)

       --学习《第一行代码总结》

         安卓中常用的存储方式有3种分别是:1、文件存储 2、SharedPreferences存储 3、SQLite数据库存储。这里我们主要看文件存储和SharedPreferences存储。     

1、 文件存储

        文件存储是Android中最基本的一种数据存储方式,它不对存储的内容进行任何的格式化处理,所有数据都是原封不动地保存到文件当中的,因而它比较适合用于存储一些简单的文本数据或二进制数据。

1、1 将数据存储到文件中

         Contect类中提供了一个 openFileOutput() 方法,可以用于将数据存储到指定的文件中。这个方法接收两个参数,第一个参数是文件名,在文件创建的时候使用的就是这个名称,注意这里指定的文件名不可以包含路径,因为所有的文件都是默认存储到/data/data/<package name>/files/目录下的。第二个参数是文件的操作模式,主要有两种模式可选,MODE_PRIVATE和MODE_APPEND。其中MODE_PRIVATE是默认的操作模式,表示当指定同样文件名的时候,所写入的内容将会覆盖原文件中的内容,而MODE_APPEND则表示如果该文件已存在,就往文件里面追加内容,不存在就创建新文
件。

        OpenFileOutputStream方法返回的是一个 FileOutputStream 对象,得到了这个对象之后就可
以使用Java流的方式将数据写入到文件中了。以下是一段简单的代码示例,展示了如何将一段文本内容保存到文件中:

public void save() {
String data = "Data to save";
FileOutputStream out = null;
BufferedWriter writer = null;
try {
out = openFileOutput("data", Context.MODE_PRIVATE);
writer = new BufferedWriter(new OutputStreamWriter(out));
writer.write(data);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (writer != null) {
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

这里通过openFileOutput() 方法能够得到一个 FileOutputStream 对象,然后再借助它构建出一
个 OutputStreamWriter 对象,接着再使用 OutputStreamWriter 构建出一个 BufferedWriter对象,这样你就可以通过 BufferedWriter 来将文本内容写入到文件中了。

        下面我们就编写一个完整的例子,借此学习一下如何在Android项目中使用文件存储的技术。首先创建一个FilePersistenceTest项目,并修改activity_main.xml中的代码,如下所示:

<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="Type something here"
/>
</LinearLayout>

这里只是在布局中加入了一个EditText,用于输入文本内容。其实现在你就可以运行一下
程序了,界面上肯定会有一个文本输入框。然后在文本输入框中随意输入点什么内容,再
按下Back键,这时输入的内容肯定就已经丢失了,因为它只是瞬时数据,在活动被销毁
后就会被回收。而这里我们要做的,就是在数据被回收之前,将它存储到文件当中。修改
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);
}
@Override
protected void onDestroy() {
super.onDestroy();
String inputText = edit.getText().toString();
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);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (writer != null) {
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

可以看到,首先我们在 onCreate() 方法中获取了EditText的实例,然后重写了 onDestroy()
方法,这样就可以保证在活动销毁之前一定会调用这个方法。在 onDestroy() 方法中我们
获取了EditText中输入的内容,并调用 save() 方法把输入的内容存储到文件中,文件命名
为data。

1、2 从文件中读取数据

类似于将数据存储到文件中, Context 类中还提供了一个 openFileInput() 方法,用于从文件中读取数据。这个方法要比 openFileOutput() 简单一些,它只接收一个参数,即要读取的文件名,然后系统会自动到/data/data/<package name>/files/目录下去加载这个文件,并返回一个 FileInputStream 对象,得到了这个对象之后再通过Java流的方式就可以将数据读取出来了。 

以下是一段简单的代码示例,展示了如何从文件中读取文本数据:

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();
}

         在这段代码中,首先通过 openFileInput() 方法获取到了一个 FileInputStream 对象,然后借助它又构建出了一个 InputStreamReader 对象,接着再使用 InputStreamReader 构建出一个 BufferedReader 对象,这样我们就可以通过 BufferedReader 进行一行行地读取,把文件中所有的文本内容全部读取出来,并存放在一个 StringBuilder 对象中,最后将读取到的内容返回就可以了。

        了解了从文件中读取数据的方法,那么我们就来继续完善上一小节中的例子,使得重新启动程序时EditText中能够保留我们上次输入的内容。修改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)) {
edit.setText(inputText);
edit.setSelection(inputText.length());
Toast.makeText(this, "Restoring succeeded", Toast.LENGTH_SHORT).show();
}
}...
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();
}
}

可以看到,这里的思路非常简单,在 onCreate() 方法中调用 load() 方法来读取文件中存
储的文本内容,如果读到的内容不为 null ,就调用EditText的 setText() 方法将内容填充
到EditText里,并调用 setSelection() 方法将输入光标移动到文本的末尾位置以便于继续
输入,然后弹出一句还原成功的提示。 load() 方法中的细节我们在前面已经讲过,这里
就不再赘述了。
注意,上述代码在对字符串进行非空判断的时候使用了 TextUtils.isEmpty() 方法,这是
一个非常好用的方法,它可以一次性进行两种空值的判断。当传入的字符串等于 null 或
者等于空字符串的时候,这个方法都会返回 true ,从而使得我们不需要先单独判断这两
种空值再使用逻辑运算符连接起来了。
现在重新运行一下程序,刚才保存的Content字符串肯定会被填充到EditText中,然后编写
一点其他的内容,比如在EditText中输入Hello,接着按下Back键退出程序,再重新启动程
序,这时刚才输入的内容并不会丢失,而是还原到了EditText中.

2、 SharedPreferences存储

不同于文件的存储方式,SharedPreferences是使用键值对的方式来存储数据的。也就是说,当保存一条数据的时候,需要给这条数据提供一个对应的键,这样在读取数据的时候就可以通过这个键把相应的值取出来。而且SharedPreferences还支持多种不同的数据类型存储,如果存储的数据类型是整型,那么读取出来的数据也是整型的;如果存储的数据是一个字符串,那么读取出来的数据仍然是字符串。这样你应该就能明显地感觉到,使用SharedPreferences来进行数据持久化要比使用文件方
便很多,下面我们就来看一下它的具体用法吧。

2、1 将数据存储到SharedPreferences中

要想使用SharedPreferences来存储数据,首先需要获取到 SharedPreferences 对象。Android中主要提供了3种方法用于得到 SharedPreferences 对象。 

01.
Context类中的 getSharedPreferences() 方法此方法接收两个参数,第一个参数用于指定SharedPreferences文件的名称,如果指定的文件不存在则会创建一个,SharedPreferences文件都是存放在/data/data/<packagename>/shared_prefs/目录下的。第二个参数用于指定操作模式,目前只有MODE_PRIVATE这一种模式可选,它是默认的操作模式,和直接传入0效果是相同的,表示只有当前的应用程序才可以对这个SharedPreferences文件进行读写。
02.
Activity
类中的 getPreferences() 方法这个方法和Context中的 getSharedPreferences() 方法很相似,不过它只接收一个操作模式参数,因为使用这个方法时会自动将当前活动的类名作为SharedPreferences的文件名。
03.
PreferenceManager类中的 getDefaultSharedPreferences() 方法这是一个静态方法,它接收一个 Context 参数,并自动使用当前应用程序的包名作为前缀来命名SharedPreferences文件。得到了 SharedPreferences 对象之后,就可以开始向SharedPreferences文件中存储数据了,主要可以分为3步实现。
(1) 调用 SharedPreferences 对象的 edit() 方法来获取一个 SharedPreferences.Editor
对象。
(2) 向 SharedPreferences.Editor 对象中添加数据,比如添加一个布尔型数据就使
用 putBoolean() 方法,添加一个字符串则使用 putString() 方法,以此类推。
(3) 调用 apply() 方法将添加的数据提交,从而完成数据存储操作。

通过一个例子来体验一下SharedPreferences存储的用法吧。新建一个SharedPreferencesTest项目,然后修改activity_main.xml中的代码,如下所示: 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/save_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Save data"
/>
</LinearLayout>

 这里我们不做任何复杂的功能,只是简单地放置了一个按钮,用于将一些数据存储到SharedPreferences文件当中。然后修改MainActivity中的代码,如下所示:

public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button saveData = (Button) findViewById(R.id.save_data);
saveData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SharedPreferences.Editor editor = getSharedPreferences("data",
MODE_PRIVATE).edit();
editor.putString("name", "Tom");
editor.putInt("age", 28);
editor.putBoolean("married", false);
editor.apply();
}
});
}
}

可以看到,这里首先给按钮注册了一个点击事件,然后在点击事件中通过getSharedPreferences() 方法指定SharedPreferences的文件名为data,并得到了SharedPreferences.Editor 对象。接着向这个对象中添加了3条不同类型的数据,最后调用 apply() 方法进行提交,从而完成了数据存储的操作。很简单吧?现在就可以运行一下程序了,进入程序的主界面后,点击一下Save data按钮。这时的数据应该已经保存成功了,不过为了证实一下,我们还是要借助File Explorer来进行查看。打开Android Device Monitor,并点击File Explorer标签页,然后进入到/data/data/com.example.sharedpreferencestest/shared_prefs/目录下,可以看到生成了一个data.xml文件.

2、2 从SharedPreferences中读取数据 

使用SharedPreferences来存储数据是非常简单的,不过下面还有更好的消息,其实从SharedPreferences文件中读取数据会更加地简单。 SharedPreferences 对象中提供了一系列的 get 方法,用于对存储的数据进行读取,每种 get 方法都对应了SharedPreferences.Editor 中的一种 put 方法,比如读取一个布尔型数据就使用 getBoolean() 方法,读取一个字符串就使用 getString() 方法。这些 get 方法都接收两个参数,第一个参数是键,传入存储数据时使用的键就可以得到相应的值了;第二个参数是默认值,即表示当传入的键找不到对应的值时会以什么样的默认值进行返回。
我们还是通过例子来实际体验一下吧,仍然是在SharedPreferencesTest项目的基础上继续
开发,修改activity_main.xml中的代码,如下所示: 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/save_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Save data"
/>
<Button
android:id="@+id/restore_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Restore data"
/>
</LinearLayout>

 这里增加了一个还原数据的按钮,我们希望通过点击这个按钮来从SharedPreferences文件
中读取数据。修改MainActivity中的代码,如下所示:

public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
Button restoreData = (Button) findViewById(R.id.restore_data);
restoreData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SharedPreferences pref = getSharedPreferences("data", MODE_PRIVATE);
String name = pref.getString("name", "");
int age = pref.getInt("age", 0);
boolean married = pref.getBoolean("married", false);
Log.d("MainActivity", "name is " + name);
Log.d("MainActivity", "age is " + age);
Log.d("MainActivity", "married is " + married);
}
});
}
}

        可以看到,我们在还原数据按钮的点击事件中首先通过 getSharedPreferences() 方法得到了 SharedPreferences 对象,然后分别调用它的 getString() 、 getInt() 和 getBoolean()方法,去获取前面所存储的姓名、年龄和是否已婚,如果没有找到相应的值,就会使用方法中传入的默认值来代替,最后通过Log将这些值打印出来。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值