我不是罗大锤我不是罗大锤

我不是罗大锤

我不是罗大锤我不是罗大锤

我不是罗大锤

首页首页
分类分类
标签标签
友情链接友情
日记日记
开发中
博客仍在开发中。
Powered byNola
Android 持久化技术Android 持久化技术

Android 持久化技术

&Android

允许评论

4 年前

Android 持久化技术包括文件存储、SharedPreferences、数据库三种。

一、文件存储

Context 类中提供了 openFileOutput() 与 openFileInput() 方法用于将数据存储到文件夹中与读取数据,所有文件都默认存储在:/data/data/file/

1.存储

openFileOutput 方法有两个参数,第一个参数是文件名,第二个参数是操作模式,有 MODE_PRIVATE、MODE_APPEND 两种,分别代表覆盖文件和追加内容,默认为第一个。

fun save(text: String) {
    try {
        val output = openFileOutput("data",Context.MODE_PRIVATE)
        val writer = BufferedWriter(OutputStreamWriter(output))
        writer.use {
            it.write(text)
        }
    } catch (e: IOException) {
        e.printStackTrace()
    }
}

2.读取

openFileInput 接受一个文件名参数。

fun load() : String {
    val content = StringBuilder()
    try {
        val input = openFileInput("data")
        val reader = BufferedReader(InputStreamReader(input))
        reader.use {
            reader.forEachLine {
                content.append(it)
            }
        }
        return content.toString()
    } catch (e: IOException) {
        e.printStackTrace()
        return ""
    }
}

二、SharedPreferences存储

SharedPreferences 属于键值对存储、类型存储,有两种方法可以获取 SharedPreferences 实例。SharedPreferences 只有 MODE_PRIVATE 这一种操作模式。数据存储在:/data/data/shared_prefs/

  1. Context Context的getSharedPreferences()方法,接受两个参数,分别是文件名称与操作模式。
  2. Activity Activity的getPreferences()方法,只接受一个操作模式参数,文件名默认为Activity类名。

1.存储

// 存储需要先获取 SharedPreferences.Editor 对象
val editor = getSharedPreferences("data",Context.MODE_PRIVATE).edit()
editor.putString("name","Tom")
// 提交数据
editor.apply()

2.读取

val sp = getSharedPreferences("data",Context.MODE_PRIVATE)
val name = sp.getString("name")

3.简化 SharedPreferences 用法

// 方法一:自建高阶函数
fun SharedPreferences.open(
        block: SharedPreferences.Editor.() -> Unit) {
    val editor = edit()
    editor.block()
    editor.apply()
}
// 使用自建高阶函数
fun main(){
    SharedPreferences.open {
        putString("name","Tom")
    }
}

// 方法二:使用Google KTX扩展库(原理与上方自建类似)
fun main(){
    SharedPreferences.edit {
        putString("name","Tom")
    }
}

三、SQLite 数据库存储

Android 为了让我们更方便管理数据库,提供了一个抽象类 SQLiteOpenHelper,有两个抽象方法 onCreate() 和 onUpgrade(),分别用来创建和升级数据库。

SQLiteOpenHelper 中有两个重要的实例方法,getReadableDatabase() 和 getWritableDatabase(),这两个方法都可以创建或打开一个现有数据库,当数据库不可写入时, getReadableDatabase() 方法将以只读方式打开,而 getWritableDatabase() 方法将出现异常。

// 首先实现我们自己的数据库类
// SQLiteOpenHelper 第三个参数返回自定义 Cursor,传 null 即可
// name 和 version 分别代表数据库名和版本
class MyDatabaseHelper(val context: Context, name: String, version: Int) : 
        SQLiteOpenHelper(context,name,null,version) {
    private val createBook = "create table Book (" + 
            " id integer primary key autoincrement," + 
            "author text," + 
            "price real," + 
           "pages integer," + 
           "name text)"    
    override fun onCreate(db: SQLiteDatabase) {
        // 执行 SQL 代码创建 Book 表
        db.execSQL(createBook)
    }
    
    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
        // 更新数据库
    }
}

1.创建数据库和表

调用 getWritableDatabase() 方法后会先检测 ”BookStore.db” 数据库是否存在,如果不存在就执行 onCreate() 方法并执行上面添加的创建 ”Book” 表的 SQL 代码。

// 创建 BookStore.db 数据库,指定当前版本为 1
val dbHelper = MyDatabaseHelper(this,"BookStore.db",1)
dbHelper.writableDatabase

2.升级数据库

假设几周后需要添加 Category 表,先在 onCreate() 方法中添加建表的SQL代码,但是如果老用户直接覆盖安装新版,在调用 getWritableDatabase() 方法时系统检测到已经存在 ”BookStore.db” 表就不会去调用 onCreate() 方法了,这时就需要使用到升级数据库 onUpgrade() 方法了。

class MyDatabaseHelper(...) ... {
    ...
    private val createCategory = "..."
    override fun onCreate(...) {
        ...
        //创建Category表
        db.execSQL(createCategory)
    }
    
    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
        // 如果用户设备上数据库版本小于等于1就执行
        if(oldVersion <= 1) {
            db.execSQL(createCategory)
        }
    }
}

//创建数据库,指示版本为2
val dbHelper = MyDatabaseHelper(this,"BookStore.db",2)
dbHelper.writableDatabase

这样的话,如果用户安装新版,就会执行 onUpgrade() 方法,并新建 Category 表。如果用户第一次就安装了 2 版,也会执行 onCreate() 方法中的新建 Category 表命令。这样不管是老用户覆盖安装,还是新用户直接安装最新版,都能始终保持与最新版数据库内容一致。

3.添加数据

insert() 方法接收三个参数:表名、在未指定添加数据的情况下给某些可为空列自动赋值 null、 ContentValues 对象。

// 用SQLiteDatabase方法添加数据
val dbHelper = MyDatabaseHelper(this, "BookStore.db", 2)
val db = dbHelper.writableDatabase
val values = ContentValues().apply{
    put("name", "The Da Vinci Code")
    put("author", "Dan Brown")
    put("pages", 454)
    put("price", 16.96)
}
db.insert("Book", null, values)

// 用SQL添加数据
db.execSQL("insert into Book(name,author,pages,price)" + 
    " values(?,?,?,?)", arrayOf("The Da Vinci Code","Dan Brown",
    "454","16.96"))

4.更新数据

update() 方法接收四个参数:表名、ContentValues 对象、三四参数用于约束更新。

// 用SQLiteDatabase方法更新数据
val dbHelper = MyDatabaseHelper(this, "BookStore.db", 2)
val db = dbHelper.writableDatabase
val value = ContentValues().put("price", 10.99)
db.update("Book", value, "name=?", arrayOf("The Da"))

// 用SQL更新数据
db.execSQL("update Book set price = ? where name = ?",
    arrayOf("10.99", "The Da Vinci Code"))

5.删除数据

delete() 方法接收三个参数:表名、二三参数用于约束删除对象。

// 用SQLiteDatabase方法删除数据
val dbHelper = MyDatabaseHelper(this, "BookStore.db", 2)
val db = dbHelper.writableDatabase
db.delete("Book", "pages > ?", arrayOf("500"))

// 用SQL删除数据
db.execSQL("delete from Book where pages > ?", arrayOf("500"))

6.查询数据

query() 方法参数最少的一个也要七个参数,返回 Cursor 对象,下面是参数详解: Android持久化技术_1.png

// 用SQLiteDatabase方法查询数据
val dbHelper = MyDatabaseHelper(this, "BookStore.db", 2)
val db = dbHelper.writableDatabase
// 查询Book表所有数据
val cursor = db.query("Book",null,null,null,null,null,null)
if(cursor.moveToFirst()) {
    do{
        //遍历Cursor对象
        val name = cursor.getString(cursor.getColumnInedx("name"))
    } while(cursor.moveToNext())
    cursor.close()
}

// 用SQL查询数据
val cursor = db.rawQuery("select * from Book",null)

四、使用事务

比如银行程序用户 1 给另一个用户 2 汇钱,为了防止在用户1账户中的钱被扣除后出现异常导致这笔钱凭空消失,可以使用事务。

db.beginTransaction()    // 开启事务
try{
    db.delete("Book",null,null)    // 删除数据
    val values = ContentValues().apply{...}
    db.insert("Book",null,values)    // 添加数据
    db.setTransactionSuccessful()    //事务执行成功
} catch(e: Exception) {
    e.printStackTrace()
} finally {
    db.endTransaction()    //结束事务
}
//现在在调用setTransactionSuccessful()方法之前如果出现异常的话。
//所有已经更改的数据将会恢复

五、简化 ContentValues 使用

KTX 提供的 contentValuesOf()

val values = contentValuesOf("name" to "Game of Thrones",
    "author" to "George Martin", "pages" to 720,
    "price" to 20.85)
db.insert("Book",null,values)
目录
一、文件存储
1.存储
2.读取
二、SharedPreferences存储
1.存储
2.读取
3.简化 SharedPreferences 用法
三、SQLite 数据库存储
1.创建数据库和表
2.升级数据库
3.添加数据
4.更新数据
5.删除数据
6.查询数据
四、使用事务
五、简化 ContentValues 使用
暂无评论