这是Android学习笔记的第14篇,之前关于界面方面的学习总结暂时告一段落。这篇主要详细介绍Android开发过程中数据存储的常见几种方式。
一、概述
二、Shared Preferences 简单键值对
三、Internal Storage 内部存储
四、External Storage 外部存储
五、SQLite数据库
六、Network Connection 网络存储
七、总结
一、概述
在平常的应用开发中,数据存储应该是我们经常要接触的内容,同时也是相当重要的部分。例如,要开发一个课程表的App,如果用户将自己的课程数据输入,但是下次登录时却看不到之前的数据,那这样的App还有价值吗,我们需要采取某种方式把数据存储下来。Android为我们的数据存储提供了很多选择,根据不同的存储需要,可以采取不同的方式。
总的来说,数据存储有两种类别,一种是存储在本地,另一种是通过网络把数据存储在服务器端。本文主要介绍数据在本地存储的4种基本方式,包括Shared Preferences(简单键值对存储),Internal Storage (内部存储),External Storage (外部存储),SQLite数据库。
二、Shared Preferences 简单键值对
1、概述
Shared Preferences,直译就是共用的配置信息,它的使用很简单,主要是采用键值对的形式来保存应用的一些常用配置等少量的数据,且这些数据的格式非常简单。例如,用户登录时提供一个选择按钮,询问是否记住密码,这时就可以使用这种方式。
2、例子
Shared Preferences平时在使用过程中比较简单,经常用到的有两个类接口,SharedPreferences和SharedPreferences.Editor。其中,后面的SharedPreferences.Editor主要是用于修改数据。下面以一个例子来讲下它的用法。
1、下图是个用户登录界面,输入用户名和密码后登录前可以选择是否记住密码,如果记住了,那么下次登录的时候EditText里就直接显示上次的用户名和密码。
登录界面2、布局文件layout_preferences.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:gravity="center"
android:orientation="vertical"
android:padding="8dp">
<EditText
android:id="@+id/et_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="用户名">
<requestFocus />
</EditText>
<EditText
android:id="@+id/et_userpasswd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="密码" />
<CheckBox
android:id="@+id/cb_keep"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="记住密码" />
<Button
android:id="@+id/btn_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="登录" />
</LinearLayout>
3、Activity里的代码SharedPreActivity 。
public class SharedPreActivity extends Activity {
SharedPreferences sp;
SharedPreferences.Editor spEditor;
private static final String FILE_USER = "FILE_USER_LO";
private static final String KEY_KEEP = "keeppswd";
private static final String KEY_USERNAME = "username";
private static final String KEY_USERPASSWD = "userpswd";
private EditText etUserName, etUserPasswd;
private Button btnLogin;
private CheckBox cbKeep;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_preferences);
initView();
initData();
}
private void initView() {
etUserName = (EditText) findViewById(R.id.et_username);
etUserPasswd = (EditText) findViewById(R.id.et_userpasswd);
cbKeep = (CheckBox) findViewById(R.id.cb_keep);
btnLogin = (Button) findViewById(R.id.btn_login);
}
//初始化数据
private void initData() {
sp = getSharedPreferences(FILE_USER, Context.MODE_PRIVATE);
//获取之前是否点击了保存密码
cbKeep.setChecked(sp.getBoolean(KEY_KEEP, false));
//如果点击了就获取密码
if (cbKeep.isChecked()) {
etUserName.setText(sp.getString(KEY_USERNAME, ""));
etUserPasswd.setText(sp.getString(KEY_USERPASSWD, ""));
}
btnLogin.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
String userName = etUserName.getText().toString().trim();
String userPasswd = etUserPasswd.getText().toString().trim();
if (cbKeep.isChecked()) {
funDataSave(userName, userPasswd, 1);
} else {
funDataSave(userName, userPasswd, 0);
}
}
});
}
private void funDataSave(String username, String userpassword, int type) {
spEditor = sp.edit();
if (type == 0) {
spEditor.putBoolean(KEY_KEEP, false);
spEditor.putString(KEY_USERNAME, "");
spEditor.putString(KEY_USERPASSWD, "");
} else {
spEditor.putBoolean(KEY_KEEP, true);
spEditor.putString(KEY_USERNAME, username);
spEditor.putString(KEY_USERPASSWD, userpassword);
}
spEditor.apply();
}
}
3、用法解析
- Shared Preferences使用过程中,接口SharedPreferences通过getSharedPreferences(String name, int mode)方法来实例化,其中name是配置文件名,mode是配置文件操作模式。我们这里传入Context.MODE_PRIVATE,表示该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容。操作模式还有MODE_WORLD_READABLE,表示当前文件可以被其他应用读取。
MODE_WORLD_WRITEABLE,表示当前文件可以被其他应用写入 - Shared Preferences允许我们存储的数据主要有Boolean、String、Int、Float、Long等几种,如果要对数据进行操作,通过SharedPreferences.edit()实例化接口SharedPreferences.Editor,之后通过putFloat(String key, float value)等方法可以将指定键名的数据存储到配置文件里,通过getFloat(String key, float defValue)等可以获取到指定键名的数据。
- 对数据进行操作,必须要提交才能生效,可以选择commit()或者apply(),官方推荐采用apply(),因为这种方法是异步进行的。
三、Internal Storage 内部存储
1、概述
Internal Storage,内部存储,主要是将数据文件保存到设备的内部存储中。
2、用法与解析
- 将数据写入到指定文件
/**
* 写入数据到内部存储
*
* @param wData 数据
* @param filename 写入到的文件
*/
private void funInternalWrite(String wData, String filename) {
FileOutputStream fos;
try {
fos = openFileOutput(filename, Context.MODE_PRIVATE);
fos.write(wData.getBytes());
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
- 读取指定文件的内容
private String funInternalRead(String filename) {
String rData = "";
try {
FileInputStream fis = openFileInput(filename);
byte[] bytes = new byte[fis.available()];
fis.read(bytes);
fis.close();
rData = new String(bytes);
} catch (IOException e) {
e.printStackTrace();
}
return rData;
}
- 其它有用的方法
getFilesDir() 得到文件的绝对路径
getDir() 在内部存储上创建目录,如果已经存在就打开。
deleteFile() 删除指定文件
fileList() 返回应用存储的文件列表
四、External Storage 外部存储
1、概述
每个Android设备都支持一个共享的外部存储,可以允许你存储文件。它可能是一个可拆卸的SD卡,也可能是不能拆卸的。
2、用法与解析
- 添加权限
- 检查外部存储是否可用
- 外部存储操作
- 添加权限
这里需要注意, WRITE_EXTERNAL_STORAGE其实包括了读写两个权限,如果只需要读可以只添加读权限。
2、检查外部存储是否可用
private static boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
3、数据写入外部存储指定文件。
public static void funExternalWrite(String data, String filename) {
FileOutputStream fos = null;
File file = new File(Environment.getExternalStorageDirectory(), filename);
if (isExternalStorageWritable()) {
try {
fos = new FileOutputStream(file, true);
fos.write(data.getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
4、读取外部存储指定文件
public static String funExternalRead(String filename) {
FileInputStream fileInputStream = null;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
File file = new File(Environment.getExternalStorageDirectory(), filename);
if (isExternalStorageWritable()) {
try {
fileInputStream = new FileInputStream(file);
int len = 0;
byte[] data = new byte[1024];
while ((len = fileInputStream.read(data)) != -1) {
byteArrayOutputStream.write(data, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return new String(byteArrayOutputStream.toByteArray());
}
五、SQLite数据库
Android provides full support for SQLite databases. Any databases you create will be accessible by name to any class in the application, but not outside the application.
Android完全支持SQLite数据库,应用中的任何数据库都可以通过名称来访问,但是别的应用不可以,当然应用间的数据共享可以用Content Provider来实现。
SQLite数据库使用的一般步骤有:
-
新建一个继承自SQLiteOpenHelper 的子类,在其中完成数据库的初始化操作,包括创建表等等。重写onCreate方法在里面完成数据表的创建,onUpdate是数据库更新时调用的。下面这张图是个简单的例子。
SQLiteOpenHelper 类 -
对数据库进行操作前一般先获取一个SQLiteDatabase 对象,利用它我们可以完成对数据库表的操作,比如增删改查等等。下面这张图是一个对数据表执行删除操作的函数,应该比较清楚。
数据库表删除指定记录
SQLite数据库其实很强大,熟悉常见的sql语句,可以很简单地完成对数据库表的操作。
六、Network Connection 网络存储
网络存储主要是把数据存储到服务器端,这部分内容我会在以后的博客中继续更新,欢迎大家继续关注。
七、总结
应用中数据存储的常见几种方式就是以上这些,内容提供者Content Provider的使用过程中通常会用到SQLite数据库,这个部分的内容大家可以看我之前的第3篇文章。最后,关于数据存储方式部分的使用,稍后会贴出源码链接。
网友评论