0
点赞
收藏
分享

微信扫一扫

【达内课程】数据存储


文章目录

  • ​​数据存储介绍​​
  • ​​SharedPreferences:偏好设置​​
  • ​​I/O存储/文件存储​​

数据存储介绍

数据存储也称之为数据持久化。表现为将程序处理过程中需要保存的数据存储到硬盘的某个文件中。在 Android 中,数据存储主要区分为:
1、偏好设置
2、IO存储/文件存储
3、SQLite数据库存储
4、网络存储

SharedPreferences:偏好设置

偏好设置通常用于存储用户在使用软件时的个性化设置。存储的数据通常存在 K-V 关系,且数据量较小,数据是私有的(不需要共享给其他应用程序)。

偏好设置的本质是使用 XML 存储数据,存储的文件将存在 /data/data/应用程序包名/shared_prefs/ 文件夹下。

如果在设置-应用程序-当前应用-清除数据,会清楚所有偏好设置的设置项。

【保存数据】
1、通过 Context 对象的 ​​​getSharedPreferences(String name,int mode)​​​方法获取 SharedPreferences 对象,其中,第 1 个参数标识存储偏好设置的文件的文件名,不包括扩展名;第 2 个参数表示文件的访问类型,取值为 Context.MODE_PREVATE
2、通过 SharedPreferences 对象的 ​​​edit()​​​方法,获取文件的编辑工具(Editor 接口类型)的对象
3、调用 Editor 对象的 ​​​put???(String key, ?? value)​​​ 系列方法执行编辑,即编辑文件,将数据写入文件内部
4、调用 Editor 对象的 ​​​commit()​​ 方法提交写入

【读取数据】
1、通过 Context 对象的 ​​​getSharedPreferences(String name, int mode)​​​方法获取 SharedPreferences 对象,其中,第 1 个参数表示存储偏好设置的文件的文件名,不包括扩展名,第 2 个参数表示文件的访问类型,取值为 Context.MODE_PREVATE
2、通过 SharedPreferences 对象的 ​​​get???()​​ 系列方法读取数据

举例:通过 SharedPreferences 保存数据

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="15dp">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="请输入用户名" />

<EditText
android:id="@+id/et_username"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="请选择性别" />

<RadioGroup
android:id="@+id/rg_male"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<RadioButton
android:id="@+id/rb_male"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="男" />

<RadioButton
android:id="@+id/rb_female"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="女" />

</RadioGroup>

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="请输入年龄" />

<EditText
android:id="@+id/et_age"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number" />

<Button
android:id="@+id/btn_submit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="提交" />

</LinearLayout>

MainActivity

public class MainActivity extends AppCompatActivity {
private EditText etUserName;
private RadioButton rbGenderMale;
private RadioButton rbGenderFeMale;
private EditText etAge;
private Button btnSubmit;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

initView();
setListeners();
showData();
}

private void initView() {
etUserName = findViewById(R.id.et_username);
rbGenderMale = findViewById(R.id.rb_male);
rbGenderFeMale = findViewById(R.id.rb_female);
etAge = findViewById(R.id.et_age);
btnSubmit = findViewById(R.id.btn_submit);
}

private void setListeners() {
btnSubmit.setOnClickListener(view -> {
String username = etUserName.getText().toString().trim();
String gender = rbGenderMale.isChecked() ? "男" : "女";
int age = Integer.parseInt(etAge.getText().toString());
//执行保存
String name = "user-info";//保存偏好设置的文件的文件名,不需要指定扩展名
int mode = Context.MODE_PRIVATE;//文件的访问模式
SharedPreferences sharedPreferences = getSharedPreferences(name, mode);
SharedPreferences.Editor editor = sharedPreferences.edit();

editor.putString("_username", username);
editor.putString("_gender", gender);
editor.putInt("_age", age);
editor.commit();

Toast.makeText(MainActivity.this, "保存成功", Toast.LENGTH_SHORT).show();
});
}

private void showData() {
//显示偏好设置中的数据
String name = "user-info";
int mode = Context.MODE_PRIVATE;
SharedPreferences sharedPreferences = getSharedPreferences(name, mode);
String username = sharedPreferences.getString("_username", null);
String gender = sharedPreferences.getString("_gender", null);
int age = sharedPreferences.getInt("_age", 0);

etUserName.setText(username);
if ("女".equals(gender)) {
rbGenderFeMale.setChecked(true);
} else {
rbGenderMale.setChecked(true);
}
etAge.setText(age == 0 ? "" : (age + ""));
}
}

我们把程序运行到手机上
【达内课程】数据存储_数据存储
可以在 Android Studio 查看 Device File Explorer ,选择手机
【达内课程】数据存储_缓存_02
查看 user-info.xml 的文件内容
【达内课程】数据存储_缓存_03

I/O存储/文件存储

如果需要存储的数据表现为独立的文件,则需要使用 IO 方式存储,例如下载得到的图片、歌曲等,或软件运行过程中产生的日志文件等。

使用 IO 存储时,如果是纯问比文件(.txt 文件、.xml 文件、.log 文件)这些文件内部的数据一共是不被频繁读取和解析的。

【存储分类】
IO 存储根据存储的文件位置、是否需要共享给其他应用程序、数据的时效性,可以分为:
1、内部存储
2、外部存储
3、内部缓存存储
4、外部缓存存储

【内部存储】
可以通过 ​​​openFileInput(String name)​​​方法获取 FileInputStream 对象,可以通过 ​​openFileOoutput(String name, int mode)​​ 方法获取 FileInputStream 对象。

内部存储的文件都是私有的,所以在设置访问模式时始终使用 MODE_PRIVATE。

内部存储的文件将保存在 /data/data/应用程序报名/files 文件夹。

内部存储的文件也可以通过系统的设置功能进行清除。

与内部存储相关的方法还有:
​​​String[] fileList()​​​:获取文件列表
​​​boolean deleteFile(String name)​​​:删除文件
​​​File getDir(String name,int mode)​​​:获取某个自定义的文件夹的 File 对象,如果自定义文件夹,系统会默认添加 ​​app_​​ 做位前缀,例如指定的文件夹名称是 logs 时,实际表现为 app_logs,不过开发者可以无视前缀,获取文件夹对象时始终使用 logs 即可。

【外部存储】
外部存储的义件是存储在 sdcard 下的,这些文件都是公有的。
外部存储是不可靠的,因为外部存储本身并不是始终可用的,并且,保存在外部存储中的文件可能被用户或其它 APP 删除或修改。
外部存储的访问应该允分使用 Enviroment 类来获取相关文件夹对象等。实现外部存储依然使用 Java 中的 IO。

【内部缓存存储】
缓存:暂时保存,用于存储有效性特征的数据或文件。
通过调用​​​File getCacheDir()​​​方法,可以获取内部缓存的文件夹的 File 对象,然后再创建出缓存文件的 File 对象,最终创建 FileInputstream / FileoutputStrearm实现文件的读写。
内部缓存将由 Android 系统进行管理和维护,会将该文件夹的容量控制在一定池围之内。
内部缓存也是应用程序私有的,即其它应用程序无法访问。

【外部缓存存储】
与内部缓存不同,外部缓存对应的存储目录是在 sdcard 下的。

通过调用​​File getExternalcacheDir()​​方法,可以获取外部缓存的文件夹的 File 对象,然后再创建出缓存文件的 File 对象,最终创建 FileInputstream/Fileoutputstream 实现文件的读写。

外部缓存是公有的。外部缓存与一般外部存储一样,都是不可靠的。

外部缓存不由 Android 系统进行管理和维护,但是,开发者应该制定一系列的逻辑进行管理,例如定期清除,或达到一定容量后清除等。

栗子

【达内课程】数据存储_缓存_04

xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="20dp">


<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="请输入你的个性签名" />

<EditText
android:id="@+id/et_sign"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/btn_submit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="提交"/>

</LinearLayout>

MainActivity

public class MainActivity extends AppCompatActivity {
private EditText et_sign;
private Button btnSubmit;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

initView();
setListeners();
loadData();
}

private void loadData() {
FileInputStream fis = null;
InputStreamReader isr = null;
BufferedReader br = null;
StringBuffer content = new StringBuffer();

try {
fis = openFileInput("sign.txt");
isr = new InputStreamReader(fis);
br = new BufferedReader(isr);


String line;
while ((line = br.readLine()) != null) {
content.append(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

et_sign.setText(content);
}

private void setListeners() {
btnSubmit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String content = et_sign.getText().toString();
FileOutputStream fos = null;

try {
fos = openFileOutput("sign.txt", MODE_PRIVATE);
//getBytes():将一个字符串转化为一个字节数组byte[]的方法
byte[] bytes = content.getBytes();
fos.write(bytes);
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
fos = null;//让它被虚拟机视为垃圾
} catch (IOException e) {
e.printStackTrace();
}
}
}

Toast.makeText(MainActivity.this, "保存成功", Toast.LENGTH_SHORT).show();
}
});
}

private void initView() {
et_sign = findViewById(R.id.et_sign);
btnSubmit = findViewById(R.id.btn_submit);
}
}

栗子

xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="20dp">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="请输入你的个性签名" />

<EditText
android:id="@+id/et_sign"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<Button
android:id="@+id/btn_submit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="提交" />

</LinearLayout>

MainActivity

public class MainActivity extends AppCompatActivity {
private EditText et_sign;
private Button btnSubmit;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

initView();
setListeners();
loadData();
}

private void initView() {
et_sign = findViewById(R.id.et_sign);
btnSubmit = findViewById(R.id.btn_submit);
}

private void setListeners() {
btnSubmit.setOnClickListener(view -> {
String content = et_sign.getText().toString();
FileOutputStream fos = null;

try {
fos = openFileOutput("sign.txt", MODE_PRIVATE);
//getBytes():将一个字符串转化为一个字节数组byte[]的方法
byte[] bytes = content.getBytes();
fos.write(bytes);
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
fos = null;//让它被虚拟机视为垃圾
} catch (IOException e) {
e.printStackTrace();
}
}
}

Toast.makeText(MainActivity.this, "保存成功", Toast.LENGTH_SHORT).show();
});
}

private void loadData() {
FileInputStream fis = null;
InputStreamReader isr = null;
BufferedReader br = null;
StringBuffer content = new StringBuffer();

try {
fis = openFileInput("sign.txt");
isr = new InputStreamReader(fis);
br = new BufferedReader(isr);


String line;
while ((line = br.readLine()) != null) {
content.append(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

et_sign.setText(content);
}
}

运行程序到手机上
【达内课程】数据存储_android_05
【达内课程】数据存储_xml_06
【达内课程】数据存储_android_07
以上这些内容是上课时讲的,我的博客中还有一篇关于数据存储的文章,是根据《第一行代码 第三版》写的,对于数据存储写的更全面,还有 kotlin 版本代码。????​​​传送门​​

举报

相关推荐

0 条评论