1.數據持久化的方式
Android中主要提供了三種數據持久化的方式:文件存儲、SharePreferences存儲以及數據庫存儲
2.文件存儲
fun save(inputText:String){
val output=openFileOutput("data", Context.MODE_PRIVATE)
val write=BufferedWriter(OutputStreamWriter(output))
write.use {
it.write(inputText)
}
}
借助于Context的openFileOutput方法
第一個參數是文件名,這個參數不能帶路徑,因為所有的文件默認保存到/data/data/<packagename>/files/目錄下
第二個參數是文件的操作模式,MODE_PRIVATE:表示文件名相同內容會直接覆蓋 MODE_APPEND:表示文件存在則直接追加
這里使用了一個use的擴展函數,這個函數中的代碼全部執(zhí)行完之后會自動將外層的流關閉,不需要再手動寫finally進行流關閉了
另外Kotlin中沒有try catch,不需要像java那些寫try catch代碼了
3.文件中讀取數據
fun read():String{
val content=StringBuilder()
val input=openFileInput("data")
val reader=BufferedReader(InputStreamReader(input))
reader.use {
reader.forEachLine {
content.append(it)
}
}
return content.toString()
}
借助openFileInput方法
forEachLine是Kotlin的一個內置函數,它會將讀到的每一行內容都回到Lambda表達式中,然后完成拼接
4.將數據保存到SharedPreferences
fun saveToSharePreference(content:String){
getSharedPreferences("data",Context.MODE_PRIVATE).edit().apply {
putString("name","jack")
putInt("age",16)
putString("desc",content)
apply()
}
}
SharePreference保存數據是以鍵值對的方式保存的
保存的路徑是/data/data/<packagename>/shared_prefs/目錄下
5.從SharedPreferences讀取數據
fun readFromSharePreference() {
getSharedPreferences("data", Context.MODE_PRIVATE).apply {
val name = getString("name", "")
val age = getInt("age", 0)
val desc = getString("desc", "")
Log.d(TAG, "name=$name,age=$age,desc=$desc")
}
}
6.SQLite數據庫存儲
想使用數據庫google提供了SQLiteOpenHelper來完成這些操作
class MySqliteDataHelper(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)"
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)
showToast("create books success")
}
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")
}
//...
}
}
這個是抽象類,需要一個寫一個實現(xiàn)類,這個抽象類構造方法有四個參數
第一個是Context上下文
第二個是數據庫名字
第三個是允許查詢數據庫返回一個自定義的cursor
第四個是當前數據庫的版本號
onCreate方法只會調用一次,當數據庫存在之后,onCreate方法便不會執(zhí)行了,所以如果需要有調整比如添加一個新表或者添加一個字段等需要在onUpgrade方法中執(zhí)行
數據庫創(chuàng)建之后,存在的路徑是/data/data/<packagename>/目錄下
初始化SQLiteOpenHelper之后,可以調用getReadableDatabase或者getWriteableDatabase
getReadableDatabase:這個是以只讀的方式打開數據庫
getWriteableDatabase:這個是可讀可寫的方式打開數據庫(如果磁盤滿了,會出現(xiàn)異常)
查看數據庫中的表是否創(chuàng)建成功,可以借助Android studio插件 Database Navigator,安裝插件之后,Android studio 左側會出現(xiàn)DB Browser工具,將數據庫從sd卡導出來直接導入到這個工具就可以查看了。
7.對數據庫進行增刪查改
fun insertData(view: View){
val value=ContentValues().apply {
put("name","斗破蒼穹")
put("author","tom")
put("pages",454)
put("price",16.68)
}
writableDatabase.insert("Book",null,value)
}
給Book表插入一條數據,insert方法,第一個參數是表名字,第二個參數是用戶未指定添加的時候給某些可為空的列自動賦值NULL,第三個參數是ContentValues對象。
fun updateData(view: View){
writableDatabase = mySqliteDataHelper.writableDatabase
val value=ContentValues()
value.put("price",12.68)
writableDatabase.update("Book",value,"name=?", arrayOf("斗破蒼穹"))
}
更新數據,第二個參數是更新的內容,第三個參數是where占位符,第四個參數是占位符的值
fun deleteData(view: View){
writableDatabase=mySqliteDataHelper.writableDatabase
writableDatabase.delete("Book","price>?", arrayOf("12.68"))
}
刪除數據,第二個參數是where占位符,第三個參數是占位符的值
fun queryData(view: View){
writableDatabase=mySqliteDataHelper.writableDatabase
val cursor = writableDatabase.query(
"Book", null, null,
null, null, null, null
)
while (cursor.moveToNext()){
val name = cursor.getString(cursor.getColumnIndex("name"))
val page = cursor.getInt(cursor.getColumnIndex("pages"))
}
}
查詢數據,并對結果進行遍歷,query方法參數有些多,不過好多時候不需要全部寫
//參數介紹
第一個參數:表名
第二個參數:查詢的列名字
第三個參數:指定where的約束條件
第四個參數:為where指定的展位符設置的值
第五個參數:指定需要group by
第六個參數:對group by的結果進行一步約束
第七個參數:指定查詢結果的排序
8.數據庫事務操作
//使用事務
fun useTransaction(){
writableDatabase=mySqliteDataHelper.writableDatabase
writableDatabase.beginTransaction()
writableDatabase.delete("Book",null,null)
val values = ContentValues().apply {
put("name","斗羅大陸")
put("author","tom")
put("pages",454)
put("price",15.68)
}
writableDatabase.insert("Book",null,values)
writableDatabase.setTransactionSuccessful()
writableDatabase.endTransaction()
}
數據庫的事務中的內容,必須全部完成才可以,否則已經執(zhí)行的語句會直接回滾,保留原來的舊數據,銀行轉賬等都需要用到事務操作。
9.數據庫升級
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")
}
//...
}
數據庫升級,最好是根據oldVersion進行判斷,這樣如果從2升到3,只會執(zhí)行后邊的if語句,如果是從1升級到3則會執(zhí)行兩個語句,這樣不管版本如何進行升級都可以保證數據庫的表結構是最新的,而且表中的數據也不會丟失。