文件存储

写入文件

Context提供了一个openFileOutput()方法,他需要两个参数,第一个参数是文件名,不准带路径,因为所有的文件都会默认保存到/data/data/<package name>/files/下,第二个参数是操作模式,主要有MODE_PRIVATEMODE_APPEND一个是覆写,一个是追加。
openFileOutput()返回的是一个outputstream()

读取文件

Context提供了一个openFileInput(),他只需要一个参数,就是文件名,它返回的是一个inputstream流。系统会自动到/data/data/<package name>/files/下寻找文件。然后你通过流的方式读取文件。

setSelection()是Edittext中,用来调节光标位置的方法。

SharedPreferences存储

在SharedPreferences中,他是通过key-value的方式存储数据的。而且它存储后的内容是通过xml进行保存的。
它被保存在一个固定的目录中/data/data/<packagename>/shared_prefs/

存储数据

  1. Context提供了一个getSharedPreferences()方法,通过该方法可以获取一个对象,它接收两个参数,第一个参数是文件名。第二个参数是操作模式。目前只有MODE_PRIVATE其他均已被废除。
  2. Activity提供了一个getPreferences()方法,它只需要填如操作模式,它默认把文件名定义为activity的类名。

存储主要可以分为3步实现。

  1. 调用SharedPreferences对象的edit()方法获取一个
    SharedPreferences.Editor对象。
  2. 向SharedPreferences.Editor对象中添加数据,比如添加一个布尔型数据就使用
    putBoolean()方法,添加一个字符串则使用putString()方法,以此类推。
  3. 调用apply()方法将添加的数据提交,从而完成数据存储操作。

获取数据

  1. 调用SharedPreferences对象的edit()方法获取一个SharedPreferences.Editor对象。
  2. 调用getString()等方法来获取。他也需要两个参数,第一个参数是key键,第二个参数是,如果没读取出来,设置某个默认值。

数据库存储

Android内置了SQLite数据库为我们使用。这个数据库很小巧。而且运行超快。

SQLiteOpenHelper

这是android为我们提供的一种帮助类,通过这个类,可以简单的创建和使用数据库。
它本身是一个抽象类,我们需要继承并实现他的两个抽象方法:onCreate(),onUpgrade()。然后这两个方法中实现创建数据库和升级数据库的逻辑。
他还有两个重要的实例方法:getReadableDatabase()getWritableDatabase()。这两个方法都可以创建或者打开一个数据库。并返回一个能对数据库进行读写的对象。这两个方法不同的是,如果数据库不可写入,如磁盘已满,那么read获得的是一个只能读的对象。而write会直接报错。
SQLiteOpenHelper有两个构造方法可以重写。
一般使用参数较少的这个:
四个参数:context,数据库名,可以自定义的cursor,当前数据库的版本号。
数据库文件创建完后会存放在/data/data/<packagename>/databases/目录下。

创建数据库

  1. 首先先构建好SQLiteOpenHelper,并完成onCreateonUpgrade的重写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class MyDataBaseHelper(val context: Context, val name: String, val version: Int) :
SQLiteOpenHelper(context, name, null, version) {
//sql语句
private val createBook = "create table Book (" +
" id integer primary key autoincrement," +
"author text," +
"price real," +
"pages integer," +
"name text)"
//sql语句
private val createCategory = "create table Category (" +
"id integer primary key autoincrement," +
"category_name text," +
"category_code integer)"

override fun onCreate(db: SQLiteDatabase) {
db.execSQL(createBook)
db.execSQL(createCategory)
Toast.makeText(context, "Creat Success", Toast.LENGTH_SHORT).show()
}

override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL("drop table if exists Book")
db.execSQL("drop table if exists Category")
onCreate(db)
}

}
> execSQL中都是填入sqluvjv
  1. 在activity中,构建一个MyDataBaseHelper
    1
    val dbHelper = MyDataBaseHelper(this,"BookStore.db",1)
  2. 与某个按钮绑定,创建数据库
    1
    2
    3
    createDatabase.setOnClickListener {
    dbHelper.writableDatabase
    }
    然后就完成了创建过程
    这里要注意的点:(1):writableDatabase该方法会先判断是否存在数据库,如果已经存在则只打开,否则将会创建并调用onCreat()方法。然后完成数据库的创建。(2):但是如果数据库已经存在了,你需要再添加新表或者对数据库结构的操作,就必须删除数据库重新调用onCreate方法。或者将
    1
    val dbHelper = MyDataBaseHelper(this,"BookStore.db",1)
    的版本号改成比1大的任意自然数。他就会调用onUpgrade()方法。这样子就可以实现数据库的升级。

修改数据

调用SQLiteOpenHelper的getReadableDatabase()或getWritableDatabase()方法是可以用于创建和升级数据库的,不仅如此,这两个方法还都会返回一个SQLiteDatabase对象,借助这个对象就可以对数据进行CRUD操作了。
CRUD,四个基本操作就是增删改查。这里不做过于详细的示例,只说明大致用法:

  • insert():
参数 解释
表名 需要添加数据的表
默认值 当未指明某列的数据时,都会填充该数据
传入的数据 他需要接收ContentValues对象,这个对象可以通过put方法重载获得新方法
例如:
1
2
3
4
5
6
7
8
val values1 = ContentValues().apply {
// 开始组装第一条数据
put("name", "The Da Vinci Code")
put("author", "Dan Brown")
put("pages", 454)
put("price", 16.96)
}
database.insert("Book", null, values1) // 插入第一条数据
  • update()
参数 解释
表名 需要添加数据的表
传入的数据 他需要接收ContentValues对象,这个对象可以通过put方法重载获得新方法
约束
约束
第三四个数据使用来约束更新那几行的数据,不指定的话,就会默认更新所有行
示例:
1
2
3
4
5
6
7
8
database.update(
"Book",
ContentValues().apply {
put("price", 10.99)
},
"name = ?",
arrayOf("The Da Vinci Code")
)
  • delete()
参数 解释
表名 需要添加数据的表
约束
约束
第二三个数据都是用来约束行的
无示例
  • query()
    用来查询数据的,他接收到参数很多,如图:

    示例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    val 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的方法

  1. beginTransaction()方法开启一个事务
  2. 调用setTransactionSuccessful()表示事务已经执行成功
  3. endTransaction()结束事务

数据库升级小技巧

首先有一些前情提要:

  1. 如果库中已经存在某张表,如果再创建同名的表,将会导致报错,除非你把原表删除
  2. 一个应用程序的版本迭代会有多种可能,第一版到第二版甚至到第n版。如果因为没设置好升级功能。直接跳过版本迭代。导致的数据丢失。会使用户失去体验感。
    因此采取了以下措施:
    onUpgrade()方法中,根据版本号进行迭代,如下:
    1
    2
    3
    4
    5
    6
    7
    8
    override 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")
    }
    }
    这样子的好处就是,你从不同的版本迭代,都尽量帮你升级到最新版且保持数据不丢失