從 greenDAO 轉換到 Room 的那些坑

Sean Lin
verybuy-dev
Published in
6 min readDec 23, 2017

前言:

Verybuy 的 Android APP ORM 原本是使用 greenbot 的 greenDAO

因為最近 greenDAO 的更新進度趨緩

加上前陣子把原本的 RxJava 1 升級到了 RxJava 2

greenDAO 一直沒有提供 RxJava 2 的支援

然後 Google 在今年釋出了新的架構組件 Android Architecture Components

裡面的 ORM 庫 Room 看起來還不錯用

官方的東西也比較不怕被放生

於是就趁著專案之間的空檔把原本的 greenDAO 換成了 Room

也產生的這篇文章來跟大家分享我這裡面踩到的一些小坑

希望能幫以後也有這個需求的人路能走的比較平緩一點

一、移除 greenDAO 的依賴

先在 Gradle 就把所有 greenDAO 的依賴都拿掉了

要注意的是不只 model 下的 Gradle

project 下的依賴也要拿掉

二、移除相關的 annotation

greenDAO 使用了 annotation 來標注 Entity 和一些欄位相關的資訊

這一步先把這些相關的 annotation 給刪掉

三、 移除產生 database 相關的程式碼

把初使化 greenDAO 相關的程式碼給移除掉

四、Clean 專案

因為 greenDAO 會自動地產生一些 Dao 相關的程式碼

所以我們要把他們給清乾靜

點擊 Android Studio 上面的 Build -> Clean project

等他跑完就可以了

到這裡我們大致上就跟 greenDAO 脫勾了

五、加入 Room 的依賴

我們要先在 project 下的 Gradle 加入對 Google maven 的依賴

接下來要在 model 下的 Gradle 加入對 Room 的依賴

上面兩個完成後點上面黃色資訊框內的 Sync gradle.

六、建立 Room 的 Entity

這裡跟 greenDAO 一樣我們要指定我們需要的 Entity

指定的方式也很簡單

跟 greenDAO 一樣加入一個 @Entity 的 annotation 就可以了

如果有需要的話我們可以在後面指定我們想使用的 table 名稱

接下來指定我們的主鍵跟每個參數對應的 field 名稱就可以了

這邊因為當初 greenDAO 產生的 table 和 field 名稱和我預期 Room 自動產生的名稱好像不太一樣

所以這邊都使用自已指定的名稱

不然 Room 是預設會動產生相關內容的

七、建立 DAO 物件

這裡跟 greenDAO 裡面不一樣的地方是我們要自已建立 DAO

greenDAO 則是會幫我們把這一步給做掉了

不過建立的方式也不會很難

我們只要照著官方文件把我們需要的 SQL 語法給打進去就好了

這邊 Room 有一個很厲害的地方

如果我們的語法或是下的參數有錯誤的話

在編譯階段時編譯就會提示我們了

所以不用太擔心這邊

八、建立 Database

這邊我們要建立 Room 的 Database

建立方式也是照著官方的文件建立就可以了

九、修改我們使用到資料庫的地方

這邊要把 APP 內使用到資料庫的地方做一些相對應的修改

每個人狀況可能不太一樣

只要看自已的情形修改成自已所需要的東西就可以了

十、資料庫的版本變更

當上面的步驟都完成後

我們就可以開始執行 APP 了

沒意外的話一開始產生資料庫的地方就會噴錯了

錯誤題示應該會是因為版本的問題

然後會跟你說把板本給成2就可以順利執行了

我們就照著把板本從 1 改成 2 再執行一次

結果還是一樣噴錯了

這次的錯誤是說 Room 不知道怎麼來做版本的升級

接下來我們有兩條路走

① 如果不想保留原本的資料的話

那很簡單我們只要在產生資料庫的地方加上 .fallbackToDestructiveMigration() 就可以了

② 通常我們應該會想保留住原本的資料

那我們要告訴 Room 我們的資料庫怎麼升級版本

方法也很簡單

因為我們不希望原本的內容有所變更

所以寫一個空的搬移規則

再把產生資料庫的地方加入這個規則就可以了

十一、RxJava 2 線程處理

一般來說大部份的人在做完前面的步驟後就可以正常執行了

不過 Verybuy 的問題卻卡在了線程的問題上

我們都知道不可以將費時的資料處理放在主線程

DB 相關的資料當然也都要放在非主線程做

但 Verybuy 的 APP 卻在執行資料庫操做時

一直跳出不可以將 DB 操做放在主線程的錯誤

即使我已經很確定有做線程的調度處理了還是跳出這個錯誤

後來經過一步一步重新檢視後

發現問題出在 Observable

因為這個 APP 當初開始寫的時候是使用 RxJava 1

所以使用的都是 Observable

而 Room 在這邊應該要使用的是有帶背壓處理的 Flowable

所以把原本使用的 Observable 改成使用 Flowable 一切就正常執行了

--

--