當前位置:
首頁 > 最新 > 我所了解的Android資料庫框架——DBFlow

我所了解的Android資料庫框架——DBFlow

今日科技快訊

美國總統唐納德·特朗普今天在匹茲堡發表公開演講,他表示,他已經親自打電話給蘋果首席執行官蒂姆·庫克,稱他是個「了不起的人」,並感謝他在美國的投資。蘋果此前曾稱,會將大量海外現金轉回美國。特朗普承認,他最初以為庫克的意思是數億美元,而不是數千億美元,他也沒想到一家公司竟然能對一個國家有這麼大規模的投資。

作者簡介

明天就是周六啦, 提前祝大家周末愉快!

本篇文章來自DthFish的投稿,詳細地分析了View的繪製流程,希望對大家有所幫助。

DthFish的博客地址:

https://www.jianshu.com/u/ea86fdbeb6c2

簡介

為啥要寫資料庫呢?公司的項目一直在進行著調整,整個項目的 module 已經超過 20,為了做到徹底解耦,我們的組的扛把子可謂是大刀闊斧,還多次向我表達了我們的 storage 模塊需要調整的感慨。先說說現狀,目前項目中使用的是 Ormlite,總體的感覺就是使用起來還是要寫很多代碼,看著之前的升級版本的邏輯頭大。由於構建和升級的邏輯都在 storage 模塊,所以要添加和修改表的話就要一定會修改到這個模塊的代碼,說白了還是耦合。

所以需求就是兩點:

上面兩點是我學習了解資料庫框架的目的,所以 DBFlow 也只是學習和嘗試的框架之一,其他的後續再說。

簡單說明一下,本文使用的是 DBFlow 的 4.1.2 版,也是截止目前為止的最新版本,在 github 上也可以看到,目前 DBFlow 還提供了一系列拓展,包括對 kotlin 的支持,Rxjava 的支持,資料庫加密等。當然我是帶著目的來的,所以我還是會主要關註上面提出來的兩點需求,至於一些詳細的使用還是儘力吧。

配置

為了後面多 Module 使用方便,先在項目中創建 config.gradle 文件,當然這個不是必須的。

對項目的 build.gradle 文件做以下修改:

ddd

在 app Module 中的 build.gradle 中添加依賴

到這裡已經配置完畢了,下面我們開始愉快的創建資料庫了。

創建資料庫與表

新建 App 繼承 Application,並在其中初始化:

新建資料庫

新建表

新建 Product 類,並用註解@Table標註,指定它的資料庫為 AppDatabase;用@PrimaryKey標註 id 為主鍵,並且為自增長;用@Column標註 name 為表中的一列。

這裡我們的表算是建完了,只需要點擊 AndroidStudio 的 Build -> Make Project 之後,就可以在 appuildgeneratedsourceaptdebug 目錄下找到生成的類 Product_Table,在裡面可以看到一些 SQL 語句。

注意:這裡我們繼承的 BaseModel 是 DBFlow 給我們提供的,並不是我們自己項目中的,所以有人可能有疑問:我可不可以不繼承它?答案是可以的,差別僅僅增刪改查的操作上有所不同。

CRUD

DBFlow 對數據的增刪改查已經做了封裝,使用起來比較簡單,也不很容易理解。

Insert

對於向資料庫插入數據的操作,對於已經繼承了 BaseModel 的 bean,我們可以直接 new 一個出來,給相應的屬性賦值之後,直接調用 save() 方法,數據就保存完畢了,代碼如下。

另外,這裡我們並沒有給 Product 的主鍵 id 賦值,但是在保存完之後這個 id 就被賦值了。

Query

數據的查詢,這裡舉了一個簡單但是平時使用較為頻繁的例子。從前文我們可以知道 Product_Table 是 apt 給我們生成的,使用起來也很靈活易懂,當然其他的更為複雜的建議大家可以查看一下官方文檔。

Update

更新和刪除可以為先查詢後操作,只要查到對應的數據,在 bean 上做修改,然後調用 update() 方法,資料庫就能修改完成。還有另一中更接近 sql 語法的方式。

Delete

與更新操作類似:

對於未繼承 BaseModel bean 的 CRUD

對於沒有繼承 BaseModel 的 bean,我們可以用以下方式進行數據操作,事實上前面的 save() 等方法最終也是通過這樣處理的。當然定義表的時候的註解不可或缺。

這裡,考慮到更新和刪除的第二種方法,嘗試了一下,果然還可以寫出類似的插入方法。

版本升級

因新建表升級

好了現在我們已經清楚了 DBFlow 的基本使用了,但是一張表不能滿足我們的需求啊!我還想創建一張 Category 表,那麼趕緊再創建個類加下注解吧。

簡單歸簡單,但是還是試一下增刪改查功能吧!

運行,之後就會發現了崩潰信息:

這裡我們遺漏了資料庫版本的升級,對於增加表格來說,DBFlow 版本升級其實很簡單,我們只要找到我們的資料庫類,並且把他的版本號加 1。

再重新運行下,我們就能在不影響 Product 表的前提下,成功新建了 Category 表了。

因修改表結構升級

DBFlow 的表結構修改是通過 Migration(https://github.com/agrosner/DBFlowDocs/blob/master/Migrations.md) 進行的,通過對它的實現,來進行對錶的操作。

雖然看到這裡,還是不知道怎麼使用它,不過不用擔心,DBFlow 已經有它的幾個現成的實現提供給我們進行使用。

下面我們就舉一個相對常見的列子來看一下如何進行表結構的修改。

首先我們先修改一下之前創建的 Product 表:

這裡我給加上了兩列 price 和 manufactuer,然後希望價格默認為 100 元,接著寫 Migration。

有疑問!如果一次升級我們不止改了一處,還有涉及到其他的修改咋辦?

看到@Migration註解中有個 priority 這裡我們姑且多建幾個 Migration 用 priority 區分優先順序來試試吧!

輸出結果為:

可以看到 priority 小的執行順序優先,如果想要指定兩個Migration 的 priority 相同的同學,就不要找不痛快了,因為沒法保證執行順序。

接下來看一下我們更新的表格內容:

1.查詢之前的數據,已經成功的添加了兩個屬性,但是 price = 0;

2.新插入一條數據後,查詢——然並軟,說好的 defaultValue 呢!你還我的 100 塊!

關於失效的defaultValue

好吧關於 defaultValue 失效我是始料未及的,在 github 上的 Issues 中查看了一下,雖然有類似的問題但是還是沒有找到正確的處理方法(希望不是我英文水平的問題),如果有同學知道正確的方法請務必聯繫我!以免我誤人子弟!

但是我嘗試出了我自己的方法。我的資料庫要升級版本 4 啦!

令我不禁想起了郭神的LitePal,對刪除列做的良心處理。

多module使用

其實說了這麼多,我最關心的還是多 module 的使用,畢竟我最初的目的還是這個。接下來的過程有些曲折,我會把過程中出現的錯誤以及處理方法都記錄下來。

創建多個Module添加依賴

這裡除去 app,我又創建了 base,special,ship 三個 module,下面看一下他們的依賴配置。

在 ship module 中新建資料庫和表

我沒有把 AppDataBase 移到 base module 中,因為我希望各個 module 維護自己的表的時候不要修改到底層的 module,所以在 ship 中創建自己的 ShipDataBase。

開始痛苦的解決問題

和前文一樣,添加插入和查詢方法,build 報錯:

What a f**k! 好吧強大的 google 指引我到 githubIssue #266。裡面信息一堆,但是我隱約找到了我要的答案:

另外還有人提出 apt 已經不維護了:

就是說,在使用 apt(咋配置就不提了,大家可以查一下) 的情況下,可以在 Ship 的 module 的 build.gradle 中添加:

那麼就可以解決問題,通過 build 的話,最終生成的類名會是 ShipGeneratedDatabaseHolder,與 app module 中的GeneratedDatabaseHolder 區別。

但是現在的問題是 apt 已經不維護了,我們是否還能通過啥方法進行處理呢?

Android註解使用之註解編譯android-apt如何切換到annotationProcessor

https://www.cnblogs.com/whoislcj/p/6148410.html

按照上文,我又修改了 Ship 的 build.gradle 文件:

編譯,報錯:

好吧再改!AndroidStudio 告訴了我們解決方案:

這次終於成功了跑起來了,我們試試插入吧!報錯:(我已經習慣了)

還好,通過錯誤我們看到說我們沒有在 Database 中註冊,可是事實上我們已經加了@Table(database = ShipDatabase.class)註解。實際上,是我們新生成的 ShipGeneratedDatabaseHolder 需要註冊。

到這裡,多 module 的使用已經介紹完啦,我先去 Stackoverflow 上替外國友人解答下這個問題!

外鍵

終於到這裡了,原來解決完上邊的多 module 使用的問題其實已經感覺篇幅有點長了,但是考慮到外鍵的重要性覺得還是有必要講一下的。

升級資料庫:給表添加外鍵

事實上一上來就會有疑問:更新資料庫的時候添加普通的一列和添加外鍵一樣嗎?

對於我們的 bean 來說添加僅僅是添加了一個成員變數,但是更新資料庫就不一樣了,因為資料庫裡面這些自定義的數據結構是通過外鍵關聯的。好吧我們又回到了資料庫版本更新的問題,但是現在這個情況都不包含在之前提過的裡面。下邊看一下我最終嘗試過後的結構:

雖然列了簡單的三步但是還是有值得思考的地方:onPreMigrate() 方法中的代碼該怎麼寫?這個 category_id 哪裡來的?

事實上 addForeignKeyColumn() 方法是在我寫版本升級的時候在 AlterTableMigration 類中發現的:

雖然注釋中有說各個參數的含義,但是事實上看了還是不知道怎麼填寫,SQLiteType 中只有一些基本的類型,最終給我提示的還是 apt 生成的 Product_Table 類。裡面有這麼一段:

結果就是把裡面的內容截取出來當參數了,運行結果也令人滿意。ps:如果這裡有誤請及時聯繫我,給我留言啊,我也是摸索出來的

一對一外鍵

兩個方法分別執行,得到:

我們發現 query 操作查出來的 category 欄位,只有 id,name 卻等於 null,修改如下:

結果:

這裡我們多執行了一步操作,調用了 Category 的 load() 方法,然後就查到了 id 為 1 的 Category 所有的信息了。

最後

說實話在寫這篇文章之前我自己寫過另一個 Demo,但是那個就沒有這篇文章舉得例子這樣簡單明了。當然 DBFlow 的還有很多細節我沒有講到,包括但不限於加密,Rxjava這些的支持。正因為我自己在學習 DBFlow 的過程中也去找了相關文章,要麼說的都比較簡單,要麼版本不是最新的,最後還是自己看文檔進行嘗試,總結一篇出來。結果也是有很多意外收穫,總之在沒有開始寫的時候我知道篇幅會很長,但是實際上更長,所以最後有幾個想講的地方也就懶得完善了,哈哈!


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 郭霖 的精彩文章:

Android組件自動註冊方案

TAG:郭霖 |