6.1 持久化简介
Android 系统中主要提供了三种方式用于简单地实现数据持久化功能,即文件存储、SharedPreference 存储以及数据库存储。
当然,除了这三种方式之外,你还可以将数据保存在手机的 SD 卡中,不过使用文件、SharedPreference或数据库来保存数据会相对更简单一些,而且比起将数据保存在 SD 卡中会更加的安全。
6.2 文件存储
文件存储是 Android 中最基本的一种数据存储方式,它不对数据进行任何格式化处理,原封不动保存。适用于存储一些简单的文本数据或二进制数据。
6.2.1 存储数据
Context类提供了一个openFileOutput()方法,用于将数据存储到指定文件中。
try {
/**
* 1.通过openFileOutput()方法来获得FileOutputStream流,然后通过此流去写入数据
* 2.param1:文件名,不可以包含路径,因为所以文件默认都存储在/data/data/<packagename>/files/目录下
* 3.param2:操作模式,主要有两种:MODE_PRIVATE、MODE_APPEND
* MODE_PRIVATE——默认模式,指定文件名相同时,写入内容将覆盖原有内容
* MODE_APPEND——追加模式,如果该文件已存在,则追加内容;否则创建文件
* ps:还有两种MODE_WORLD_READABLE、MODE_WORLD_WRITEABLE因为容易被其他应用程序操作而在Android 4.2中废弃。
*/
FileOutputStream fileOutputStream = openFileOutput("fileName", Context.MODE_APPEND);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
6.2.2 读取数据
类似于存储,Context类提供了一个openFileinput()方法,用于从文件中读取数据,接收要读取的文件名作为参数。
6.3 SharedPreferences存储
使用键值对的方式来存储数据,并且支持多种不同的数据类型存储,存的为整型,则读取的也为整型;存的为字符串,则读取的也是字符串。
6.3.1 存储数据
1. 首先需要获取到SharedPreferences对象,Android中提供了三种方式:
(1)Context 类中的 getSharedPreferences()方法
/**
* param1:指定文件名称,如果不存在则会创建一个,SharedPreferences文件都是存放在/data/data/<packagename>/shared_prefs/目录下的
* param2:操作模式,MODE_PRIVATE和MODE_MULTI_PROCESS
* MODE_PRIVATE——默认操作模式,表示只有当前的应用程序才可以对这个SharedPreferences文件进行读写,和0效果相同。
* MODE_MULTI_PROCESS——用于会有多个进程对同一个文件进行读写的情况
* MODE_WORLD_READABLE 和 MODE_WORLD_WRITEABLE 这两种模式已在 Android 4.2 版本中被废弃
*/
SharedPreferences sharedPreferences = getSharedPreferences("fileName", Context.MODE_PRIVATE);
(2)Activity 类中的
getPreferences()方法
/**
* 使用此方法会自动将当前的活动类名作为SharedPreferences的文件名
* param:模式
*/
SharedPreferences sharedPreferences1 = this.getPreferences(Context.MODE_PRIVATE);
(3)PreferenceManager 类中的
getDefaultSharedPreferences()方法
/**
* 静态方法,自动使用当前程序的包名作为前缀来命名SharedPreferences文件
* param:Context上下文
*/
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
2.调用 SharedPreferences 对象的
edit()方法来获取一个 SharedPreferences.Editor 对象。
SharedPreferences.Editor editor=sharedPreferences.edit();
3.向 SharedPreferences.Editor 对象中添加数据,比如添加一个布尔型数据就使用putBoolean 方法,添加一个字符串则使用 putString()方法,以此类推。
editor.putString("name", "Jastar");
editor.putInt("age", 26);
editor.putBoolean("married",false);
4.调用
commit()方法将添加的数据提交
editor.commit();
6.3.2 读取数据
通过SharedPreferences对象的一系列getXXX()方法,第一个参数为键值,第二个为默认值,即当传入的键找不到对应的值时则使用此值。
6.4 SQLLite数据存储
- SQLite 是一款轻量级的关系型数据库,运算速度非常快,占用资源少,通常只需要几百k的内存;
- 不仅支持标准的sql语法,还遵循数据库的ACID事务;
- 数据库文件会存放在/data/data/<packagename>/databases/目录下。
- 数据库类型:integer(整型)、real(浮点型)、text(文本类型)、blob(二进制类型)
6.4.1 SQLiteOpenHelper帮助类
为了方便管理数据库,Android专门提供了此帮助类。SQLiteOpenHelper是一个抽象类,使用时需要创建自己的类去继承。
(1)需重写以下两个方法:
onCreate(SQLiteDatabase db):创建数据库完成后调用该方法
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion):升级数据库完成后调用该方法
(2)有两个构造函数可以重写,但一般重写参数较少的就可以:
/**
* @param context 上下文对象
* @param name 数据库名(带后缀,创建数据库时使用的就是此处的名)
* @param factory 查询数据的时候返回一个自定义的Cursor,一般传入null
* @param version 当前数据库的版本号(可用于对数据库进行升级操作)
*/
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
(3)有两个非常重要的实例方法:
相同点 | 不同点 | |
getReadableDatabase() | 都可以创建或打开一个现有的数据库(存在则打开,否则创建) 并返回一个可对数据库进行读写操作的对象 | 当数据库不可写入时(如磁盘已满),该方法返回对象将以只读方式打开数据库 |
getWritableDatabase() | 当数据库不可写入时,出现异常 |
6.4.2 创建数据库
(1)创建数据库
MyDatabaseHelper helper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
helper.getWritableDatabase();
(2)创建数据表
建表一般在onCreate()方法中编写,这样当数据库创建完成时便会自动创建表,通过该方法的参数来执行:
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("sql语句");
}
(3)使用adb shell来查看已创建的表
adb 是 Android SDK 中自带的调试工具,使用它可以直接对连接在电脑上的手机或模拟器进行调试操作。
a>它存放在 sdk 的 platform-tools 目录下,如果想要在命令行中使用这个工具,就需要先把它的路径配置到环境变量里。
b>打开dos命令界面,输入adb shell,就会进入到设备控制台:
c>使用 cd 命令进入到/data/data/<packagename>/databases/目录下:
d>使用 ls 命令查看该目录下的文件
BookStore.db:创建的数据库
BookStore.db-journal:为了让数据库能够支持事务而产生的临时日志文件,通常该文件大小都为0字节。
e>使用 sqlite3 命令来打开数据库:
f>输入 .table 命令查看目前有哪些表
android_metadata:数据库创建时自动生成的,不用管。
g>输入 .schema 命令查看它们的建表语句
h> 输入 .exit 或 .quit 命令来退出数据编辑,再输入 exit(注意无点)命令即可退出设备控制台。
6.4.3 升级数据库
如果此时需求想添加其他的表,则在onCreate()方法中代码将会不起作用,因为数据库已经存在了,所以不会再执行onCreate()方法。
(1)创建SQLiteOpenHelper类实例时修改数据库版本号:
//只要版本号比创建的时候高就可以
MyDatabaseHelper helper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
helper.getWritableDatabase();
(2)数据库版本更新完成之后便会执行onUpgrade()方法:
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("建Book表的sql");
db.execSQL("建Category表的sql");
Toast.makeText(myContext, "表Book创建成功!", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//创建表之前先判断是否存在,若存在则删除,否则创建时会异常
db.execSQL("drop table if exists Book");
db.execSQL("drop table if exists Category");
//再次执行创建
onCreate(db);
}
6.4.4 CRUD操作
(1)添加
SQLiteDatabase db = dbHelper.getWritableDatabase();
//封装要插入的一条记录
ContentValues values = new ContentValues();
values.put("name", "The Da Vinci Code");
values.put("author", "Dan Brown");
values.put("pages", 454);
values.put("price", 16.96);
/**
* 插入数据
* param1:表名
* param2:用于在未指定添加数据的情况下给某些可为空的列自动赋值NULL,一般用不到,传入null即可
* param3:一个ContentValues对象,提供了一系列put()方法,只需要把表的列名和数据添加进去即可
*/
db.insert("Book", null, values);
//当有多条数据添加时,该对象也可复用,不过要记得clear一下
values.clear();
(2)更新SQLiteDatabase db = dbHelper.getWritableDatabase();
//想更新哪一列就添加哪一列的数据
ContentValues values = new ContentValues();
values.put("price", 9.9);
/**
* 更新操作
* param1:表名
* param2:要更新的数据
* param3&4:用于约束更新某一行或几行的条件,不指定的话则默认更新所有行。
* ?为占位符
*/
db.update("Book", values, "name=?", new String[]{"The Da Vinci Code"});
(3)删除
通过delete()方法,类似以上用法
(4)查询SQLiteDatabase db = dbHelper.getWritableDatabase();
/**
* 查询方法参数最少的重载就有7个
* param1:表名
* param2:查询哪几列(不指定则所有)
* param3:类似于where条件(如id=?)
* param4:类似于where条件参数(如new String[]{"1"})
* param5:group by的列(不指定则所有)
* param6:group by后进一步过滤的列(having)
* param7:排序
*/
Cursor cursor = db.query("Book", null, null, null, null, null, null);
if (cursor.moveToFirst()) {
do {
String name = cursor.getString(cursor.getColumnIndex("name"));
//....
} while (cursor.moveToNext());
}
//关闭
cursor.close();
6.4.5 使用sql操作数据库
(1)插入
db.execSQL("insert into Book (name, author, pages, price) values(?, ?, ?, ?)",new String[] { "The Da Vinci Code", "Dan Brown", "454", "16.96" });db.execSQL("insert into Book (name, author, pages, price) values(?, ?, ?, ?)",new String[] { "The Lost Symbol", "Dan Brown", "510", "19.95" });
(2)更新
db.execSQL("update Book set price = ? where name = ?", new String[] { "10.99","The Da Vinci Code" });
(3)删除
db.execSQL("delete from Book where pages > ?", new String[] { "500" });
(4)查询
db.rawQuery("select * from Book", null);
6.4.6 使用事务
SQLiteDatabase db = dbHelper.getWritableDatabase();
//开启事务
db.beginTransaction();
try {
//一系列操作
//...
//事务成功
db.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
} finally {
//结束事务
db.endTransaction();
}