第一行代碼(六)

第六章內(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ù)即可。


image.png

image.png

??這里 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"});
            }
        });
image.png
  • 刪除數(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();
            }
        });
image.png
  • 使用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è)是:

https://github.com/LitePalFramework/LitePal

  • 配置 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 中的代碼:


image.png

注意:這里是不需要自定義 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)了
}
image.png

??現(xiàn)在只要進(jìn)行任意一次數(shù)據(jù)庫(kù)的操作叫倍,BookStore.db 數(shù)據(jù)庫(kù)就會(huì)自動(dòng)創(chuàng)建出來(lái)吆倦。


image.png

??這里創(chuàng)建數(shù)據(jù)庫(kù)就會(huì)成功蚕泽。如果我們想升級(jí)數(shù)據(jù)庫(kù)须妻,也非常方便荒吏,比如绰更,我們?cè)?Book 表中添加一個(gè) press(出版社)字段儡湾,修改 Book 類徐钠,添加press 屬性和 getter/setter 方法。同時(shí)妒穴,我們想再添加一張 Category 表讼油,進(jìn)行如下操作矮台。


image.png
/**
 * Category 實(shí)體類
 */

public class Category {

    private int id;
    private String categoryName;
    private int categoryCode;

    //同樣,下面是 getter 和 setter 方法
    
}
image.png

??點(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ù)編輯

下一篇文章 http://www.reibang.com/p/1e2cb6004c90

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末谆级,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子讼积,更是在濱河造成了極大的恐慌肥照,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件勤众,死亡現(xiàn)場(chǎng)離奇詭異舆绎,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)决摧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門亿蒸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)凑兰,“玉大人掌桩,你說(shuō)我怎么就攤上這事」檬常” “怎么了波岛?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)音半。 經(jīng)常有香客問(wèn)我则拷,道長(zhǎng),這世上最難降的妖魔是什么曹鸠? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任煌茬,我火速辦了婚禮,結(jié)果婚禮上彻桃,老公的妹妹穿的比我還像新娘坛善。我一直安慰自己,他們只是感情好邻眷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布眠屎。 她就那樣靜靜地躺著,像睡著了一般肆饶。 火紅的嫁衣襯著肌膚如雪改衩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天驯镊,我揣著相機(jī)與錄音葫督,去河邊找鬼竭鞍。 笑死,一個(gè)胖子當(dāng)著我的面吹牛候衍,可吹牛的內(nèi)容都是我干的笼蛛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蛉鹿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼滨砍!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起妖异,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤惋戏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后他膳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體响逢,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年棕孙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了舔亭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蟀俊,死狀恐怖钦铺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情肢预,我是刑警寧澤矛洞,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站烫映,受9級(jí)特大地震影響沼本,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜锭沟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一抽兆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧族淮,春花似錦辫红、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至较幌,卻和暖如春揍瑟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背乍炉。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工绢片, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留滤馍,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓底循,卻偏偏與公主長(zhǎng)得像巢株,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子熙涤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,162評(píng)論 25 707
  • 本篇文章主要介紹以下幾個(gè)知識(shí)點(diǎn):SQLite 數(shù)據(jù)庫(kù)存儲(chǔ)阁苞;開源數(shù)據(jù)庫(kù)框架 LitePal。 6.3 SQLite ...
    開心wonderful閱讀 1,102評(píng)論 7 5
  • 官方介紹祠挫,RecyclerView用于在有限的窗口展現(xiàn)大量的數(shù)據(jù)那槽,其實(shí)早已經(jīng)有了類似的控件,如ListView等舔、G...
    飛行員suke閱讀 5,194評(píng)論 1 2
  • 《方言》第二 1 第二:釥骚灸、嫽,好也慌植。青徐海岱之間曰釥甚牲,或謂之嫽。好蝶柿,凡通語(yǔ)也丈钙。 釥、嫽只锭,好也著恩。青徐海岱之間曰釥院尔,...
    xcy無(wú)名閱讀 2,293評(píng)論 0 0
  • 建筑是一門技術(shù)蜻展,也是一門藝術(shù)。每個(gè)剛剛進(jìn)入校園的建筑學(xué)學(xué)生都聽過(guò)這句話邀摆,感覺這個(gè)專業(yè)好像一下子變得高大上起來(lái)纵顾,背著...
    朗月微光閱讀 1,110評(píng)論 3 81