第六章內(nèi)容主講數(shù)據(jù)持久化技術(shù)
一、數(shù)據(jù)持久化技術(shù)簡(jiǎn)介
??數(shù)據(jù)持久化技術(shù)就是將瞬時(shí)數(shù)據(jù)(存儲(chǔ)在內(nèi)存中,有可能會(huì)因?yàn)槌绦蜿P(guān)閉或其他原因?qū)е聝?nèi)存被回收而丟失的數(shù)據(jù))保存到存儲(chǔ)設(shè)備中塔粒,保證即使在手機(jī)或電腦關(guān)機(jī)的情況下鸠窗,這些數(shù)據(jù)仍然不會(huì)丟失。保存在內(nèi)存中的數(shù)據(jù)是處于瞬時(shí)狀態(tài)的绊起,而保存在存儲(chǔ)設(shè)備中的數(shù)據(jù)是處于持久狀態(tài)的盈电,持久化技術(shù)則提供了一種機(jī)制可以讓數(shù)據(jù)在瞬時(shí)狀態(tài)和持久狀態(tài)之間進(jìn)行轉(zhuǎn)換蝴簇。
??Android 系統(tǒng)中主要提供了3種方式用于實(shí)現(xiàn)數(shù)據(jù)持久化功能:文件存儲(chǔ)、SharedPreference 存儲(chǔ)以及數(shù)據(jù)庫(kù)存儲(chǔ)匆帚。當(dāng)然還可以保存在 SD 卡中熬词,不過(guò)相比之下,SD卡比較麻煩而且不安全。
二互拾、文件存儲(chǔ)
??不對(duì)存儲(chǔ)的內(nèi)容進(jìn)行任何的格式化處理歪今,所有數(shù)據(jù)都原封不動(dòng)地保存到文件中,因而比較適合存儲(chǔ)一些簡(jiǎn)單的文本數(shù)據(jù)或二進(jìn)制數(shù)據(jù)颜矿,如果想用文件存儲(chǔ)方式來(lái)保存一些較為復(fù)雜的文本數(shù)據(jù)寄猩,就需要定義一套自己的格式規(guī)范,這樣方便之后將數(shù)據(jù)從文件中重新解析出來(lái)骑疆。
-
將數(shù)據(jù)存儲(chǔ)到文件中
??Context 提供了一個(gè) openFileOutput()方法田篇,可以用于將數(shù)據(jù)存儲(chǔ)到指定的文件中。
image.png
??接下來(lái)看看用流寫入文件的操作吧
image.png
?? 然后我們可以借助 Android Device Monitor 工具來(lái)查看一下:點(diǎn)擊 Tools-->Android-->Android Device Monitor 打開可視化工具
image.png
image.png
這里我的模擬器打不開箍铭,但是后面我通過(guò)代碼證明文件存儲(chǔ)成功
?? 然后找到/data/data/<packageName>/files/目錄下就可以看到我們生成的 file 文件了斯辰,然后點(diǎn)擊導(dǎo)出按鈕導(dǎo)出到電腦上即可。 -
從文件中讀取數(shù)據(jù)
?? Context 類還提供了 openFileInput()方法坡疼,用于從文件中讀取數(shù)據(jù)。
image.png
image.png
image.png
文件存儲(chǔ)方式并不適合用于保存一些較為復(fù)雜的文本數(shù)據(jù)
三衣陶、SharedPreferenes 存儲(chǔ)
??不同于文件存儲(chǔ)柄瑰,SharedPreferences 是使用鍵值對(duì)的方式來(lái)存儲(chǔ)數(shù)據(jù)的。
-
將數(shù)據(jù)存儲(chǔ)到 SharedPreferences 中
?? 首先要獲取 SharedPreferences 對(duì)象剪况,然后添加數(shù)據(jù)教沾,最后提交
image.png
注意:SharedPreferences文件是使用 XML 格式來(lái)對(duì)數(shù)據(jù)進(jìn)行管理的 -
從 SharedPreferences 中讀取數(shù)據(jù)
?? SharedPreferences 中提供了一系列 get 方法,用于對(duì)存儲(chǔ)的數(shù)據(jù)進(jìn)行讀取译断,每種 get 方法都對(duì)應(yīng)了 SharedPreferences.Editor 中的一種 put 方法授翻。
image.png
四、SQLite 數(shù)據(jù)庫(kù)存儲(chǔ)
??SQLitte 是一款輕量級(jí)的關(guān)系型數(shù)據(jù)庫(kù)孙咪,運(yùn)算速度快堪唐,占用資源少,通常只需要幾百 KB 的內(nèi)存就足夠了翎蹈,因而特別別適合在移動(dòng)設(shè)備上使用淮菠,SQLite 不僅支持標(biāo)準(zhǔn)的 SQL 語(yǔ)法,還遵循了數(shù)據(jù)庫(kù)的 ACID 事物荤堪。
文件存儲(chǔ)和 SharedPreferences 存儲(chǔ)畢竟只使用與保存一些簡(jiǎn)單的數(shù)據(jù)和鍵值對(duì)合陵,當(dāng)需要存儲(chǔ)大量復(fù)雜的關(guān)系型數(shù)據(jù)的時(shí)候,就需要用數(shù)據(jù)庫(kù)了
Android 為了讓我們方便的管理數(shù)據(jù)庫(kù)澄阳,專門提供了 SQLiteOpenHelper 幫助類拥知,通過(guò)這個(gè)類可以非常簡(jiǎn)單地對(duì)數(shù)據(jù)庫(kù)進(jìn)行創(chuàng)建和升級(jí)
- 創(chuàng)建數(shù)據(jù)庫(kù)
image.png
??SQLiteOpenHelper 還有兩個(gè)非常重要的方法,getReadableDatabase()和 getWritableDatabase()碎赢。這兩個(gè)方法都可以打開或創(chuàng)建數(shù)據(jù)庫(kù)低剔,并返回一個(gè)可以對(duì)數(shù)據(jù)庫(kù)進(jìn)行讀寫操作的對(duì)象。不同的是揩抡,當(dāng)數(shù)據(jù)庫(kù)不可寫入的時(shí)候(比如磁盤空間已滿)户侥,getReadableDatabase()方法返回的對(duì)象將以只讀的方式去打開數(shù)據(jù)庫(kù)镀琉,而 getWritableDatabase()方法則會(huì)出現(xiàn)異常。
??當(dāng)構(gòu)建出 SQLiteOpenHelper 實(shí)例之后蕊唐,在調(diào)用 getReadableDatabase()或getWritableDatabase()方法就能創(chuàng)建數(shù)據(jù)庫(kù)了屋摔,數(shù)據(jù)庫(kù)文件保存在/data/data/<packageName>/databases/目錄下,此時(shí)替梨,重寫的 onCreate()方法也會(huì)得到執(zhí)行钓试。
image.png
??可以用 File Explorer 查看 databases 目錄下多了一個(gè) BookStore.db 文件,但是 Book 表是無(wú)法通過(guò) File Explorer 看到的副瀑,需要使用 adb shell 來(lái)對(duì)數(shù)據(jù)庫(kù)和表的創(chuàng)建情況進(jìn)行查看弓熏,當(dāng)然使用 adb 命令需要進(jìn)行配置,需要把 platform-tools 目錄配置進(jìn)去
??接下來(lái)就可以使用 adb 命令進(jìn)行查看了糠睡,這里如果用真機(jī)的話挽鞠,可能需要 root 和管理員權(quán)限,請(qǐng)看本章最后小技巧狈孔。打開命令行界面信认,輸入
adb shell
進(jìn)入到設(shè)備控制臺(tái),如圖:
image.png
然后通過(guò) cd 命令進(jìn)入項(xiàng)目的文件夾下均抽,使用 ls 命令查看目錄里的文件嫁赏。
image.png
然后進(jìn)入到 database 文件夾中,繼續(xù)查看
image.png
該目錄下有兩個(gè)數(shù)據(jù)庫(kù)文件油挥,一個(gè)是我們創(chuàng)建的 BookStore.db潦蝇,另一個(gè)則是為了讓數(shù)據(jù)庫(kù)能夠支持事物而產(chǎn)生的臨時(shí)日志文件。
??接下來(lái)要借助 sqlite 命令來(lái)打開數(shù)據(jù)庫(kù)了深寥,需要輸入
sqlite3 數(shù)據(jù)庫(kù)名
這里因?yàn)槲矣玫氖钦鏅C(jī)攘乒,真機(jī)文件中沒有包含 sqlite3文件,所以無(wú)法使用 sqlite3命令(有辦法解決惋鹅,看另一篇文章:)持灰,如果你用的是模擬器,則可以负饲。而我使用的辦法是導(dǎo)出數(shù)據(jù)庫(kù) DB 文件堤魁,用Navicat Premium 來(lái)查看數(shù)據(jù)庫(kù)文件,至于 sqlite 命令返十,我放到最后了妥泉。 -
升級(jí)數(shù)據(jù)庫(kù)
??當(dāng)時(shí)重寫的還有一個(gè)方法,onUpgrade()是用于對(duì)數(shù)據(jù)庫(kù)進(jìn)行升級(jí)的洞坑,假如說(shuō)盲链,現(xiàn)已有一張 Book 表,但是我們想添加一個(gè) Category 表,如圖:
image.png
??當(dāng)我們點(diǎn)擊按鈕刽沾,沒有彈出成功提示本慕,文件夾中也沒有多出 Category.db 文件,表示 Category 表沒有創(chuàng)建成功侧漓,如果你卸載掉程序锅尘,然后重新運(yùn)行,再點(diǎn)擊按鈕創(chuàng)建數(shù)據(jù)庫(kù)布蔗,則 Category 表創(chuàng)建成功藤违。這是因?yàn)閳D中情況纵揍,Book 表已經(jīng)存在泽谨,MyDatabaseHelper 中的 onCreate()方法都不會(huì)再執(zhí)行璧榄,這時(shí)需要用到 onUpgrade()方法了吧雹。
image.png
注意:這里之所以先要?jiǎng)h除,是因?yàn)槿绻麆?chuàng)建的時(shí)候表已經(jīng)存在了吮炕,就會(huì)直接報(bào)錯(cuò)。
??要讓 onUpgrade()方法執(zhí)行访得,就是改變 SQLiteOpenHelper 構(gòu)造方法的數(shù)據(jù)庫(kù)版本號(hào)悍抑,改成比以前大的數(shù)即可。
??這里 Category 表創(chuàng)建成功了,就表明我們升級(jí)功能起了作用记靡。
- 添加數(shù)據(jù)
??其實(shí)對(duì)數(shù)據(jù)庫(kù)的操作無(wú)非就是 CRUD摸吠,C 代表添加(Create),R 代表查詢(Retrieve)呀洲,U 代表更新(Update)道逗,D代表刪除(Delete),每種操作都對(duì)應(yīng)了一種 SQL 命令卖词,Android 提供了一系列輔助性方法坏平,使得 Android 中即使不去編寫 SQL 語(yǔ)句,也能完成 CRUD的操作锦亦。
??前面我們知道杠园,調(diào)用 SQLiteOpenHelper 的 getReadableDatabase()或getWritableDatabase()方法可用于創(chuàng)建或升級(jí)數(shù)據(jù)庫(kù)抛蚁,這兩個(gè)方法還返回了一個(gè) SQLiteDatabase 對(duì)象瞧甩,借助這個(gè)對(duì)象,我們就可以進(jìn)行一系列 CRUD 的操作了爷辙。
??SQLiteDatabase 中提供了一種 insert()方法膝晾,專門用于添加數(shù)據(jù)血当。
image.png
image.png - 更新數(shù)據(jù)庫(kù)
??多的不說(shuō)臊旭,update()方法巍扛,你懂得
findViewById(R.id.tv_update).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SQLiteDatabase sqLiteDatabase = dbHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("price",10.99);
/**
* 更新數(shù)據(jù)庫(kù)撤奸,update()方法
* 參1:表名 參2:ContentValue 存放數(shù)據(jù)的對(duì)象
* 參3:對(duì)應(yīng) SQL 的 where 部分胧瓜,而 ? 是一個(gè)占位符
* 參4:字符串?dāng)?shù)組蒲肋,為參3中的占位符指定相應(yīng)的內(nèi)容
* 其實(shí)這里參3和參4很好理解兜粘,如果用 sql 語(yǔ)句是這樣寫的:
* update Book set price = '10.99' where name = 'The Da Vinci Code'
*/
sqLiteDatabase.update("Book",contentValues,"name = ?",new String[]{"The Da Vinci Code"});
}
});
- 刪除數(shù)據(jù)
??刪除數(shù)據(jù)孔轴,delete()方法
findViewById(R.id.tv_delete).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SQLiteDatabase sqliteDatabase = dbHelper.getWritableDatabase();
/**
* 刪除數(shù)據(jù)路鹰,delete()方法
* 對(duì)應(yīng)的 sql 語(yǔ)句:
* delete from Book where pages > '500'
*/
sqliteDatabase.delete("BOOK","pages > ?",new String[]{"500"});
}
});
- 查詢數(shù)據(jù)
??查詢數(shù)據(jù)是 CRUD中最復(fù)雜的操作晋柱,使用 query()方法
findViewById(R.id.tv_query).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SQLiteDatabase sqliteDatabase = dbHelper.getWritableDatabase();
/**
* 查詢雁竞,用 query()方法碑诉,用幾個(gè)重載的方法势腮,這里說(shuō)的是參數(shù)最少的 query()方法
* 參1:表名 參2:要查詢表中的那幾列
* 參3:where 后面的約束條件 參4:where約束條件占位符對(duì)應(yīng)的具體的值
* 參5:groupBy 參6:having
* 參7:orderBy
*
* 返回一個(gè) Cursor 對(duì)象捎拯,查詢到的所有數(shù)據(jù)都存放在 Cursor 中
*/
Cursor cursor = sqliteDatabase.query("Book", null, null, null, null, null, null);
//先將 Cursor 數(shù)據(jù)指針移動(dòng)到第一行的位置
if(cursor.moveToFirst()){
do{
//遍歷 Cursor 對(duì)象署照,取出數(shù)據(jù)并打印
/**
* 解釋一下如何獲取 name 的建芙,首先,int nameIndex = cursor.getColumnIndex("name");
* 會(huì)返回"name"該列在表中所對(duì)應(yīng)的位置索引禁荸,然后將這個(gè)位置索引傳入到
* cursor.getString(nameIndex)中,就可以獲取對(duì)應(yīng)的值了
*/
String name = cursor.getString(cursor.getColumnIndex("name"));
String author = cursor.getString(cursor.getColumnIndex("author"));
int pages = cursor.getInt(cursor.getColumnIndex("pages"));
double price = cursor.getDouble(cursor.getColumnIndex("price"));
Log.d(TAG,"name = " + name);
Log.d(TAG,"author = " + author);
Log.d(TAG,"pages = " + pages);
Log.d(TAG,"price = " + price);
}while(cursor.moveToNext());
}
/**
* 記住Cursor 使用完后一定要關(guān)閉
*/
cursor.close();
}
});
- 使用SQL操作數(shù)據(jù)庫(kù)
??有些人是 SQL 大牛,在 Android 可以直接通過(guò) SQL 來(lái)操作數(shù)據(jù)庫(kù)间坐。
1竹宋、 添加數(shù)據(jù):
db.execSQL("insert into Book (name,author,pages,price) values(?,?,?,?)",new String[]{"The Da Vinci Code","Dan Brown","454","16.96"});
2蜈七、更新數(shù)據(jù):
db.execSQL("update Book set price = ? where name = ?",new String[]{"10.99","The Da Vinci Code"});
3乓土、刪除數(shù)據(jù):
db.execSQL("delete from Book where pages > ?",new String[]{"500"});
4趣苏、查詢數(shù)據(jù):
db.rawQuery("select * from Book",null);
??可以看到食磕,除了查詢的時(shí)候用到的是 rawQuery()方法彬伦,其他的全是 execSQL()方法单绑。
五、使用 LitePal 操作數(shù)據(jù)庫(kù)
??LitePal 是開源的 Android 數(shù)據(jù)庫(kù)框架歉提,采用了對(duì)象關(guān)系映射(ORM)的模式苔巨,并將數(shù)據(jù)庫(kù)功能進(jìn)行了封裝侄泽。LitePal 的主頁(yè)是:
- 配置 LitePal
??其實(shí)在 LitePal 的主頁(yè)中悼尾,已經(jīng)有非常詳細(xì)的配置信息了,這里大概說(shuō)一下吧窄刘。首先娩践,大多數(shù)的開源項(xiàng)目都會(huì)將版本提交到 jcenter 上翻伺,我們需要在 app/build.gradle 文件中聲明該開源庫(kù)的引用即可吨岭。
image.png
??然后需要配置litepal.xml
文件辣辫,app/src/main目錄下 New --> Directory魁巩,創(chuàng)建一個(gè) assets 目錄谷遂,然后在 assets 目錄下創(chuàng)建一個(gè) litepal.xml 文件,然后編輯該文件
<?xml version='1.0' encoding="utf-8"?>
<litepal>
<!--指定數(shù)據(jù)庫(kù)名-->
<dbname value="BookStore"></dbname>
<!--指定數(shù)據(jù)庫(kù)版本號(hào)-->
<version value = "1"></version>
<!--指定所有映射模式-->
<list>
</list>
</litepal>
??最后配置一下 LitePalApplication筋粗,修改 AndroidMainifest.xml 中的代碼:
注意:這里是不需要自定義 Application 的,我們看 application 標(biāo)簽中的 name 屬性蒋院,指向的是 org.litepal 中的某個(gè) Application悦污,也就是說(shuō)這個(gè) LitePalApplication,LitePal 已經(jīng)為我們創(chuàng)建好了顷啼。
??還有一個(gè)問(wèn)題钙蒙,如果說(shuō)我的項(xiàng)目已經(jīng)有自定義的 Application 了,但是我又需要使用 LitePal 怎么辦马昨?很簡(jiǎn)單鸿捧,我們可以用另一種方式:可以在我們自定義的 Application 的 onCreate() 方法中調(diào)用LitePalApplication.initialize(context)
方法即可匙奴,這種寫法就相當(dāng)于把全局的 Context 對(duì)象通過(guò)參數(shù)傳遞給了 LitePal泼菌,效果和在清單文件中配置 LitePalAppliction 是一模一樣的哗伯。
六刷钢、LitePal 的使用
- 創(chuàng)建和升級(jí)數(shù)據(jù)庫(kù)
??LitePal 采取的是對(duì)象關(guān)系映射(ORM)的模式内地,簡(jiǎn)單點(diǎn)說(shuō)阱缓,我們使用的編程語(yǔ)言是面向?qū)ο蟮恼Z(yǔ)言荆针,使用的數(shù)據(jù)庫(kù)是關(guān)系型數(shù)據(jù)庫(kù)航背,將面向?qū)ο蟮恼Z(yǔ)言和面向關(guān)系的數(shù)據(jù)庫(kù)之間建立一種映射關(guān)系玖媚,就是對(duì)象關(guān)系映射了,我們可以使用面向?qū)ο蟮乃季S來(lái)操作數(shù)據(jù)庫(kù)勺像。
??首先創(chuàng)建一個(gè) Book 實(shí)體類吟宦,并提供 getter 和 setter 方法殃姓。然后將 Book 類添加到映射模型列表中(修改litepal.xml文件)蜗侈。
/**
* Book 實(shí)體類
*/
public class Book {
private int id;
private String author;
private double price;
private int pages;
private String name;
//下面是 getter 和 setter 方法宛篇,代碼就不貼出來(lái)了
}
??現(xiàn)在只要進(jìn)行任意一次數(shù)據(jù)庫(kù)的操作叫倍,BookStore.db 數(shù)據(jù)庫(kù)就會(huì)自動(dòng)創(chuàng)建出來(lái)吆倦。
??這里創(chuàng)建數(shù)據(jù)庫(kù)就會(huì)成功蚕泽。如果我們想升級(jí)數(shù)據(jù)庫(kù)须妻,也非常方便荒吏,比如绰更,我們?cè)?Book 表中添加一個(gè) press(出版社)字段儡湾,修改 Book 類徐钠,添加press 屬性和 getter/setter 方法。同時(shí)妒穴,我們想再添加一張 Category 表讼油,進(jìn)行如下操作矮台。
/**
* Category 實(shí)體類
*/
public class Category {
private int id;
private String categoryName;
private int categoryCode;
//同樣,下面是 getter 和 setter 方法
}
??點(diǎn)擊按鈕确虱,Book 表中的 press 字段以及 Category 表也創(chuàng)建成功了校辩。
LitePal會(huì)自動(dòng)幫我們做了一項(xiàng)非常重要的工作宜咒,就是保留之前表中的所有數(shù)據(jù)故黑,這樣就不用擔(dān)心數(shù)據(jù)丟失的問(wèn)題了场晶。
- 添加數(shù)據(jù)
??觀察一下現(xiàn)有的實(shí)體類怠缸,他們沒有任何繼承結(jié)構(gòu)凯旭。因?yàn)?LitePal 進(jìn)行表管理操作的時(shí)候不需要模型類有任何的繼承結(jié)構(gòu)罐呼,但是進(jìn)行 CRUD 就不行了嫉柴,必須要繼承自 DataSupport 類才行。
這里繼承的代碼就不貼出來(lái)了瞧壮。
image.png
image.png - 更新數(shù)據(jù)
??最簡(jiǎn)單的更新方式就是對(duì)已存儲(chǔ)的對(duì)象重新設(shè)值,然后重新調(diào)用 save()方法秦忿。對(duì)于 LitePal 來(lái)說(shuō)灯谣,對(duì)象是否已存儲(chǔ)是根據(jù)調(diào)用 model.isSave()方法的結(jié)果來(lái)判斷的胎许,true 表示已存儲(chǔ)呐萨,false 表示未存儲(chǔ)谬擦。如果已經(jīng)調(diào)用過(guò) model.save()方法去添加數(shù)據(jù)的話朽缎,此時(shí) model 對(duì)象會(huì)被認(rèn)為是已存儲(chǔ)的對(duì)象话肖;或者model 對(duì)象是通過(guò) LitePal 提供的查詢 API 查出來(lái)的最筒,也會(huì)被認(rèn)為是已存儲(chǔ)的對(duì)象床蜘。
findViewById(R.id.tv_update).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Book book = new Book();
book.setName("The Lost Symbol");
book.setAuthor("Dan Brown");
book.setPages(510);
book.setPrice(19.95);
book.save();//這個(gè) save 是添加一條數(shù)據(jù)
book.setPress("10.99");
/*
* 這個(gè) save() 邢锯,此時(shí) LitePal 會(huì)發(fā)現(xiàn)當(dāng)前的 Book 對(duì)象是已
* 存儲(chǔ)的丹擎,因此不會(huì)再向數(shù)據(jù)庫(kù)中去添加一條數(shù)據(jù),而是會(huì)直接更新
* 當(dāng)前的數(shù)據(jù)榜苫。
* 但是這種更新方式只能對(duì)已存儲(chǔ)的對(duì)象進(jìn)行操作垂睬,限制性比較大。
*/
book.save();
}
});
??下面介紹一種更加靈巧的更新方式檐春。
findViewById(R.id.tv_update).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Book book = new Book();
//設(shè)置需要更新的數(shù)據(jù)
book.setPrice(14.95);
book.setPress("Anchor");
/*
執(zhí)行更新操作疟暖,需要注意的是俐巴,updateAll()方法中可以指定一個(gè)條件約束欣舵,
即 where 后面的條件部分,如果不指定條件語(yǔ)句的話缘圈,就表示更新所有數(shù)據(jù)糟把。
*/
book.updateAll("name = ? and author = ?","The Lost Symbol","Dan Brow");
}
});
這里有一點(diǎn)需要注意遣疯,如果想把一個(gè)字段設(shè)置成默認(rèn)值缠犀,是不可以使用上面 set 方法來(lái)設(shè)置數(shù)據(jù)的夭坪。比如說(shuō)室梅,我們想把 pages 字段設(shè)置成0亡鼠,不能直接調(diào)用 book.setPages(0);因?yàn)榧词共徽{(diào)用這個(gè) set 方法间涵,pages 的默認(rèn)值也是0,LitePal 是不會(huì)對(duì)這個(gè)列進(jìn)行更新的勾哩。如果你想要設(shè)置成默認(rèn)值抗蠢,就調(diào)用 book.setToDefault("pages");方法。
- 刪除數(shù)據(jù)
??使用 LitePal 刪除數(shù)據(jù)的方式主要有兩種思劳,第一種直接調(diào)用已存儲(chǔ)對(duì)象的 delete()方法即可迅矛。第二種是使用 DataSupport.deleteAll()方法來(lái)刪除數(shù)據(jù)。
findViewById(R.id.tv_delete).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
/*
參1表示刪除哪張表中的數(shù)據(jù)潜叛,后面的參數(shù)分別代表約束條件和占位符的值
注意:如果該方法不指定約束條件,就意味著要?jiǎng)h除表中所有的數(shù)據(jù)威兜。
*/
DataSupport.deleteAll(Book.class,"price < ?","15");
}
});
- 查詢數(shù)據(jù)
??LitePal 的查詢相比 SQLiteDataBase 中的查詢要方便的多销斟。
1.如果你要查詢表中的所有數(shù)據(jù),只需要這樣寫:
List<Book> books = DataSupport.findAll(Book.class);
2.查詢 Book 表中的第一條數(shù)據(jù):
Book firstBook = DataSupport.findFirst(Book.class);
3.查詢 Book 表中的最后一條數(shù)據(jù):
Book lastBook = DataSupport.findLast(Book.class);
??還可以通過(guò)連綴查詢定制更多查詢功能
1.指定查詢哪幾列數(shù)據(jù):
List<Book> books = DataSupport.select("name","author").find(Book.class);
2.指定查詢的約束條件
List<Book> books = DataSupport.where("pages > ?","400").find(Book.class);
3.指定結(jié)果的排序方式
List<Book> books = DataSupport.order("price desc").find(Book.class);
這里 desc 表示降序椒舵,asc 或者不寫表示升序排序蚂踊。
4.指定查詢結(jié)果的數(shù)量:查詢前3條數(shù)據(jù)
List<Book> books = DataSupport.limit(3).find(Book.class);
5.指定查詢結(jié)果的偏移量:查詢第2、3笔宿、4條數(shù)據(jù):
List<Book> books = DataSupport.limit(3).offset(1).find(Book.class);
6.進(jìn)行組合連綴查詢:
List<Book> books = DataSupport.select("name","author","pages").where("pages > ?","400").order("pages").limit(10).offset(10).find(Book.class);
7.LitePal 任然支持 SQL 來(lái)進(jìn)行查詢
/*
參1指定 SQL 語(yǔ)句悴势,參2指定占位符的值。
注意:findBySQL()方法返回的是一個(gè) Cursor 對(duì)象措伐。
*/
Cursor c = DataSupport.findBySQL("select * from Book where pages > ?","400");
小結(jié):
文件存儲(chǔ)適用于存儲(chǔ)一些簡(jiǎn)單的文本數(shù)據(jù)或者二進(jìn)制數(shù)據(jù)特纤,SharedPreferences 適用于存儲(chǔ)一些鍵值對(duì),數(shù)據(jù)庫(kù)存儲(chǔ)適用于存儲(chǔ)一些復(fù)雜的關(guān)系型數(shù)據(jù)侥加。
小技巧:
- EditText 我們可以調(diào)用它的 setSelection(int length)方法將輸入的光標(biāo)移動(dòng)到文本的末尾位置捧存,以便于用戶繼續(xù)輸入。
- 使用 TextUtils.isEmpt(String str)方法可以一次性進(jìn)行兩種空值的判斷担败,當(dāng)傳入的字符串等于 null 或者等于空字符串的時(shí)候昔穴,這個(gè)方法都會(huì)返回 true.
- 調(diào)用 SharedPreferences.Editor 的 clear()方法,可以將對(duì)應(yīng)的 SharedPreferences 文件中的數(shù)據(jù)全部清除掉提前。
- 上面查看數(shù)據(jù)庫(kù)文件吗货,我是用真機(jī)測(cè)試的,首先手機(jī)需要 root狈网,然后你可能會(huì)出現(xiàn)data 文件夾打不開的情況宙搬,這時(shí)要獲得管理員權(quán)限笨腥,首先輸入 adb shell命令,然后獲得管理員權(quán)限勇垛,輸入 su脖母,接著輸入
chmod 777 /data /data/data /data/data/<packageName> /data/data/<packageName>/*
即可
- sqlite 命令:輸入 sqlite3 數(shù)據(jù)庫(kù)名,這時(shí)就已經(jīng)打開數(shù)據(jù)庫(kù)了闲孤,
.table
:查看當(dāng)前數(shù)據(jù)庫(kù)中有哪些表
.schema
:查看建表語(yǔ)句
.exit
或.quit
:退出數(shù)據(jù)庫(kù)編輯