数据存储-持久化技术
使用文件存储数据
1
|
public void save(String inputText){
|
使用openFileOutput/openFileInput搭配相应的java输入输出流使用文件来存储数据。另外,记得writer.close()。
读取文件就将FileOutputStream->FileInputStream
,BufferedWriter->BufferedReader
,wirter.write->reader.redline()
1
|
public String load(){
|
使用SharedPreferences存储数据
存放数据
1
|
SharedPreferences.Editor editor = getSharedPreferences("data",MODE_PRIVATE).edit();
|
数据以xml的形式存在
取数据
1
|
SharedPreferences pref = getSharedPreferences("data",MODE_PRIVATE);//输入相对应的文件名
|
加深理解:
1
|
SharedPreferences pref;
|
使用SQLite(DBMS)创建数据库存储数据
细节理解:
1
|
dbHelper = new MyDatabaseHelpoer(MainActivity.this,"BookStore.db",null,1);//构建一个MydatabaseHelper对象
|
创建MyDatabaseHelper继承自SQLiteOpenHelper,覆写onCreate(),onCreate()中只需要包含数据库的操作就可以了(该数据库的名字即为构造函数中传入的名字)
一个MyDatabaseHelper的对象创建一个数据库,在onCreate()函数中执行对这个数据库的操作
创建好后,用ddms的explorer(顶上Tools->Android->Android Device Monitor->File Exploer
,FileExplorer里的文件目录即为模拟器的文件目录)不能看到改数据库创建的表,用adb shell(adb是一个对连接的usb设备或者模拟器的调试器)看。要使用adb,需要先配置环境变量:增加C:\Users\Gaby\AppData\Local\Android\sdk\platform-tools
到系统变量里面的Path,就可以在android studio 的terminal里使用
FileExplorer中/data/data/com.example.gaby.databasetest/databases/
目录下有两个文件
- xxx.db数据库
- xxx.db-journal是为让数据库能够支持事务而产生的临时日志文件
建表语句:
1
|
public static final String CREATE_BOOK = "create table Book ("
|
adb命令列举:
adb devices
列出当前设备adb shell
进入设备的控制台cd /data/data/com.example.gaby.databasetest/databases/
进入模拟器该文件夹下ls
列出该目录下文件夹sqlite3 BookStore.db
打开数据库
SQLite命令:
.table
显示数据库中有哪些表.schema
查看建表语句.exit
/.quit
退出改数据库select * from tableName;
(有分号) 查询该表下有哪些纪录
接着exit
退出设备控制台(adb)
注意execSQL(String s)
传入的是字符串
CRUD
以下是按Android提供过的API来做的,实际上还可直接用SQL来操作数据库,见《第一行代码》page 260
向数据库中添加数据(db.insert()) (·)Create 添加
1
|
addData.setOnClickListener(new View.OnClickListener() {
|
getWritableDatabase()和getReadableDatabase()除了升级和创建数据库,该方法本身会返回SQLiteDatabase对象。db.insert(“表名”, null, ContentValue对象)。
查询数据(db.query()) (·)Retrieve
1
|
queryData.setOnClickListener(new View.OnClickListener() {
|
db.query()
返回Cursor对象
更新数据(db.update()) (·)Update 更新
注意:在MyDatabaseHelper中的onUpgrade()方法是用于升级数据库(如 多建/删除 一张表)。而更新数据,则是在特定表上修改数据
1
|
updataData.setOnClickListener(new View.OnClickListener() {
|
删除数据(db.delete) (·)Delete 删除
1
|
deleteData.setOnClickListener(new View.OnClickListener() {
|
删除Book表中pages列值大于300的记录
数据库的事务(ACID要么全成功,要么全失败)
1
|
replaceData.setOnClickListener(new View.OnClickListener() {
|
解读:中途出现异常,db.setTransactionSuccessful()
得不到执行,当结束事务db.endTransaction()
时发现事务未成功执行,旧数据就不会被删除
升级数据库的最佳写法
需要注意以下几点:
- 当用户下载的新版本覆盖安装旧版本时,实际上安装好的新版本应用程序具备所有新功能,只是数据库还残留在上一个版本,此时如果代码如下:
1
2
3
4
5
6
7
8
9private MyDatabaseHelpoer dbHelper;
dbHelper = new MyDatabaseHelpoer(MainActivity.this,"BookStore.db",null,6);
Button createDatabase = (Button) findViewById(R.id.createDatebase);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dbHelper.getWritableDatabase();
}
});
则可视为手动更新数据库。如果将
1
|
private MyDatabaseHelpoer dbHelper;
|
直接放置在主活动的onCreate(),而不放置在某个监听中,那么伴随活动的启动,数据库就被更新了。需要注意的是,dbHelper.getWritableDatabase()
是在没有名为”BookStore.db”的数据库时就创建(执行MydatabaseHelper
的onCreate()
函数)。如果本来就有,就会去执行onUpdate()
函数,判断旧版本是哪一个,进而做出对数据库的更改
-
新版本的不光要在onUpgrade()做出更改,还应以备旧版本更新。更要在onCreate()中做出完整的创建工作,以备用户直接下载新版本
-
在
onUpgrade()
中的case
不加break
, 原因就是如果跨版本升级。比如旧版本的数据库停留在第二版,应用安装好了,且新版本的数据库是第8版,在更新数据库时就要从第二版更新到第八版,依次升级,升级结束后此时的数据库版本号为81
2
3
4
5
6
7
8
9public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion){
case 4:
db.execSQL(CREATE_MILK);
case 5:
db.execSQL("alter table Milk add column volume real");
}
}
个人想法
对于版本更新的问题,比如手机版的qq,不可能没更新一个版本就在,onUpgrade()里加一个型号,应该会要有个版本间隔(允许的最新和最旧的版本区间),不然200年以后,以腾讯的产品迭代速度,onUpgrade()里面的代码就太多了…