Android入门(数据持久化)
文件存储
写入文件
Context提供了一个openFileOutput()
方法,他需要两个参数,第一个参数是文件名,不准带路径,因为所有的文件都会默认保存到/data/data/<package name>/files/
下,第二个参数是操作模式,主要有MODE_PRIVATE
和MODE_APPEND
一个是覆写,一个是追加。
openFileOutput()返回的是一个outputstream()
读取文件
Context提供了一个openFileInput()
,他只需要一个参数,就是文件名,它返回的是一个inputstream流。系统会自动到/data/data/<package name>/files/
下寻找文件。然后你通过流的方式读取文件。
setSelection()是Edittext中,用来调节光标位置的方法。
SharedPreferences存储
在SharedPreferences中,他是通过key-value的方式存储数据的。而且它存储后的内容是通过xml进行保存的。
它被保存在一个固定的目录中/data/data/<packagename>/shared_prefs/
。
存储数据
- Context提供了一个
getSharedPreferences()
方法,通过该方法可以获取一个对象,它接收两个参数,第一个参数是文件名。第二个参数是操作模式。目前只有MODE_PRIVATE
其他均已被废除。 - Activity提供了一个
getPreferences()
方法,它只需要填如操作模式,它默认把文件名定义为activity的类名。
存储主要可以分为3步实现。
- 调用SharedPreferences对象的edit()方法获取一个
SharedPreferences.Editor对象。 - 向SharedPreferences.Editor对象中添加数据,比如添加一个布尔型数据就使用
putBoolean()方法,添加一个字符串则使用putString()方法,以此类推。 - 调用apply()方法将添加的数据提交,从而完成数据存储操作。
获取数据
- 调用SharedPreferences对象的edit()方法获取一个SharedPreferences.Editor对象。
- 调用getString()等方法来获取。他也需要两个参数,第一个参数是key键,第二个参数是,如果没读取出来,设置某个默认值。
数据库存储
Android内置了SQLite数据库为我们使用。这个数据库很小巧。而且运行超快。
SQLiteOpenHelper
这是android为我们提供的一种帮助类,通过这个类,可以简单的创建和使用数据库。
它本身是一个抽象类,我们需要继承并实现他的两个抽象方法:onCreate()
,onUpgrade()
。然后这两个方法中实现创建数据库和升级数据库的逻辑。
他还有两个重要的实例方法:getReadableDatabase()
和getWritableDatabase()
。这两个方法都可以创建或者打开一个数据库。并返回一个能对数据库进行读写的对象。这两个方法不同的是,如果数据库不可写入,如磁盘已满,那么read获得的是一个只能读的对象。而write会直接报错。
SQLiteOpenHelper有两个构造方法可以重写。
一般使用参数较少的这个:
四个参数:context,数据库名,可以自定义的cursor,当前数据库的版本号。
数据库文件创建完后会存放在/data/data/<packagename>/databases/
目录下。
创建数据库
- 首先先构建好SQLiteOpenHelper,并完成
onCreate
和onUpgrade
的重写
1 | class MyDataBaseHelper(val context: Context, val name: String, val version: Int) : |
> execSQL中都是填入sqluvjv
- 在activity中,构建一个MyDataBaseHelper
1
val dbHelper = MyDataBaseHelper(this,"BookStore.db",1)
- 与某个按钮绑定,创建数据库然后就完成了创建过程
1
2
3createDatabase.setOnClickListener {
dbHelper.writableDatabase
}
这里要注意的点:(1):writableDatabase该方法会先判断是否存在数据库,如果已经存在则只打开,否则将会创建并调用onCreat()
方法。然后完成数据库的创建。(2):但是如果数据库已经存在了,你需要再添加新表或者对数据库结构的操作,就必须删除数据库重新调用onCreate方法。或者将的版本号改成比1大的任意自然数。他就会调用1
val dbHelper = MyDataBaseHelper(this,"BookStore.db",1)
onUpgrade()
方法。这样子就可以实现数据库的升级。
修改数据
调用SQLiteOpenHelper的getReadableDatabase()或getWritableDatabase()方法是可以用于创建和升级数据库的,不仅如此,这两个方法还都会返回一个SQLiteDatabase对象,借助这个对象就可以对数据进行CRUD操作了。
CRUD,四个基本操作就是增删改查。这里不做过于详细的示例,只说明大致用法:
- insert():
参数 | 解释 |
---|---|
表名 | 需要添加数据的表 |
默认值 | 当未指明某列的数据时,都会填充该数据 |
传入的数据 | 他需要接收ContentValues对象,这个对象可以通过put方法重载获得新方法 |
例如: |
1 | val values1 = ContentValues().apply { |
- update()
参数 | 解释 |
---|---|
表名 | 需要添加数据的表 |
传入的数据 | 他需要接收ContentValues对象,这个对象可以通过put方法重载获得新方法 |
约束 | |
约束 | |
第三四个数据使用来约束更新那几行的数据,不指定的话,就会默认更新所有行 | |
示例: |
1 | database.update( |
- delete()
参数 | 解释 |
---|---|
表名 | 需要添加数据的表 |
约束 | |
约束 | |
第二三个数据都是用来约束行的 | |
无示例 |
- query()
用来查询数据的,他接收到参数很多,如图:
示例:如果其他都不填的话,默认为1
2
3
4
5
6
7
8
9
10
11
12
13
14
15val strings:StringBuilder=StringBuilder()
val cursor = database.query("Book", null, null, null, null, null, null)
if(cursor.moveToFirst()){
do{
//遍历所有cursor对象
val name = cursor.getString(cursor.getColumnIndex("name"))
val author = cursor.getString(cursor.getColumnIndex("author"))
val pages = cursor.getInt(cursor.getColumnIndex("pages"))
val price = cursor.getDouble(cursor.getColumnIndex("price"))
strings.append(name+"\t"+author+"\t"+pages+"\t"+price+"\n")
}while (cursor.moveToNext())
textView.text = strings
strings.clear()
cursor.close()
}select * from '表名'
也可以直接通过sql语言去实现这些功能
不做详细示例。凭个人喜好而学。
事务
sqlite也支持事务:
基本步骤为:
调用SQLiteDatabase的方法
- beginTransaction()方法开启一个事务
- 调用setTransactionSuccessful()表示事务已经执行成功
- endTransaction()结束事务
数据库升级小技巧
首先有一些前情提要:
- 如果库中已经存在某张表,如果再创建同名的表,将会导致报错,除非你把原表删除
- 一个应用程序的版本迭代会有多种可能,第一版到第二版甚至到第n版。如果因为没设置好升级功能。直接跳过版本迭代。导致的数据丢失。会使用户失去体验感。
因此采取了以下措施:
再onUpgrade()
方法中,根据版本号进行迭代,如下:这样子的好处就是,你从不同的版本迭代,都尽量帮你升级到最新版且保持数据不丢失1
2
3
4
5
6
7
8override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
if (oldVersion <= 1) {
db.execSQL(createCategory)
}
if (oldVersion <= 2) {
db.execSQL("alter table Book add column category_id integer")
}
}