Room數(shù)據(jù)庫包裝-通過kotlin包裝一行代碼增刪改查

本文目的在于,針對room原生api中有一些不方便的地方,基于注解與RxJava,kotlin的強大lambda表達式進行包裝節(jié)省大量開發(fā)工作。

谷歌發(fā)布了ROOM數(shù)據(jù)庫,與其他常見數(shù)據(jù)庫api的區(qū)別是,基于注解與sql,不需要像其他庫一樣去記數(shù)據(jù)庫內置的DAO的各種操作api函數(shù),數(shù)據(jù)庫遷移功能很強大而且邏輯清晰,便于維護。官方支持RxJava,對于查詢結果可以很方便的實現(xiàn)異步訂閱。

Room提供給我們的是一個基礎的有無限可能的庫,也許對于新手程序員來說,不如greendao等庫用起來足夠傻瓜式(只需要記住增刪改查的api,不需要自己去寫dao的sql語句),但是谷歌的庫都有一個特點,就是基于你的能力,可以有無限的擴展可能(databinding庫也是類似,新手覺得沒有便捷多少,但是如果你自己積累,編寫了很多自定義xml屬性,和自己改造包裝通用的工具方法,databinding甚至可以讓給你在xml中一行屬性完成listView的adapter從創(chuàng)建,填充數(shù)據(jù)一條龍服務,這點稍后會把我的基于databinding的包裝心得寫一篇文章,拋磚引玉,啟發(fā)大家想出天馬行空的使用方式)。關于數(shù)據(jù)庫的使用不做過于詳細的講解,我這里只對于從0開始組建room數(shù)據(jù)庫實踐過程中的心得,如何利用。

關于ROOM的痛點:

1.對比與其他的開源數(shù)據(jù)庫,在創(chuàng)建dao的時候,需要手動寫增刪該查,如果表很多,也有不小的工作量。

2.不進行包裝,原生使用方式基于Dao對象操作,對于增刪改查都要寫大量的rxJava的訂閱監(jiān)聽以及線程的模版代碼,這些都可以通過技術手段簡化,避免。

github地址:

GitHub - chrism1981/fastRoomDatabase: Room Database for Android, with kotlin. 基于room數(shù)據(jù)庫的包裝,快速開發(fā),一行代碼增刪改查

一.下面我們來看一下原生的Room使用過程(歸結為:Entity,Dao,DataBase三大對象):

1.對數(shù)據(jù)對象進行@entity注解處理,轉化為Entity類:比較簡單,class上標記@Entity,對于主鍵變量,標記@PrimaryKey

2.根據(jù)Entity對象,創(chuàng)建對應對DAO類,通過注解的方式,將SQL(不用害怕敲sql,用room庫的話,在敲sql的時候也是有代碼提示的,不會像寫純string一樣出現(xiàn)筆誤等情況。)語句注冊給對應對操作方法:


3. 創(chuàng)建自己的DataBase類(繼承RoomDatabase),聲明你之前創(chuàng)建的dao的操作方法


4.以查詢方法為例子,api的實際調用:獲取數(shù)據(jù)庫實例,獲取dao實例,操作dao的方法。

二.本文的包裝思路與實際操作預覽:

下面是我的包裝方法:首先解決不必要重復寫的增刪等方法。然后已一個DataBaseHelper類來包裝,操作數(shù)據(jù)庫,將rxjava的訂閱過程包裝起來,并且引入帶參數(shù)的查詢。

主要解決問題就是免去大量的模版代碼,rxjava代碼,線程操作,數(shù)據(jù)庫操作,都由

最終預覽下,我們想調用一個SearchRecordDao來查詢,獲取到一個結果list,顯示到一個textview上,最終的全部代碼如下:

一行代碼完成查詢過程,不用關心數(shù)據(jù)庫如何創(chuàng)建,dao如何創(chuàng)建,異步線程操作等等都不需要在開發(fā)時候重復去操作了。

三.大致結構與流程:

結構:

流程:


四. 主要代碼講解:

1.Dao類注解的標記:

其中@IsQuery :無參數(shù)查詢所有數(shù)據(jù);@IsQueryWithKey 帶一個參數(shù)的查詢,@IsDeleteAll :刪除全部。 以上這些方法的Sql其實都可以copy,只是表名不同。


2.DBHelper 中的工作:

當這個Dao被創(chuàng)建標記完成以后,我們馬上就可以通過操作 DBHelper來進行操作這個表的查詢,比如要調用通過 id查詢結果(getSearchRecordById()方法):傳一個key,Dao的class,成功獲取結果后的回調函數(shù)(lambda表達式)

這個調用對應都就是我們剛才在SearchRecordDao.class里的getResearchRecordById()方法,它是通過注解 @ IsQueryWithKey被識別,當我們調用時候傳的“1270030”就是id參數(shù)。

首先,通過DBHelper找到dao,然后調用dao的對應帶參數(shù)查詢方法,數(shù)據(jù)庫的關閉也在這里進行。queryListWithKey方法如下:

其中的success 和fail 類型為 (t:List)->(Unit)這個代表一個lambda表達式,

對于lambda不熟悉的同學,我簡答講解下怎么理解這個東西。

當這個表達式success(t)被調用的時候,這個方法的設計者會把他查詢到的結果(一個list<T>)通過invoke這個表達式的方式傳遞給你,以便于你的表達式在編寫的時候,就可以針對這個查詢結果出來以后,如何進行下一步工作給出方案。其中suceess(t) 就是調用lambda表達式,其實它和調用函數(shù)是一樣的。如果熟悉c,c++的同學,可以發(fā)現(xiàn),它和函數(shù)指針的概念很像。

對于用java的同學,可以這樣對照lambda和匿名內部類:

{? list-> int size = list.size() }? 可以這樣理解 ,假設又一個Success接口包含一個參數(shù)為list的方法,

success = new Success(){??

@override

public void recall(List<T> list){

int size = list.size();

} }

其實任何一個lambda表達式,都可以用一個接口來代替。而相對于接口,lambda可以說,是去掉了定義接口類,創(chuàng)建匿名對象這一過程,可以用一個式子來完成全部工作。

3.Dao中的代碼:

dao中的具體實現(xiàn)方法,都在BaseDao中,由父類實現(xiàn)了 insert,delete ,update等方法。子類中主要就是聲明query方法,并用注解中寫好Sql語句。

BaseDao:

這個方法雖然是在BaseDao中,但我們但子類Dao中會繼承這個方法,當它在運行時候,反射獲取的所有method是當前子類的所有方法,這樣我們在寫B(tài)aseDao的時候,就可以實現(xiàn)找到將來任意一個子類中代表了有參查詢@IsQueryWithKey的方法,并且調用這個方法,在父類里就預先寫好RxJava的訂閱。

最后的結果就是使用時候直接調用DbHepler.queryWithKey(..),然后Dbhelper會自己去找到BaseDao的query方法,BaseDao在找到當前子類Dao的query方法。完成查詢。

總結:當然這只是一個思路,滿足大部分app中數(shù)據(jù)庫簡單應用,比如一些復雜的sql語句查詢,肯定會有,但不會是每一條查詢都是復雜的。我們簡化包裝,如果可以覆蓋一半以上的應用場景,那它就是值得的。

后期還有很多可以擴展的地方,比如帶參數(shù)的查詢,可以擴展到多個參數(shù),同一個Dao中,可能需要多個含單參數(shù)查詢的方法,比如按name查詢,按age查詢,我們同樣可以擴展實現(xiàn),比如在@IsQueryWithKey注解中接受參數(shù),注解可以接受基礎數(shù)據(jù)類型和枚舉。 這樣一來,對于2個不同的單參數(shù)查詢方法,可以用 @IsQueryWithKey(name) 和@IsQueryWithKey(age)來標記不同方法,在項目中也可以維護一個常量表,用于代表這些查詢參數(shù),這樣在調用Dbhelper來查詢的時候,通過傳入對于參數(shù),就可以區(qū)分當前想要查詢的條件是什么。

最后附上地址

github地址:

GitHub - chrism1981/fastRoomDatabase: Room Database for Android, with kotlin. 基于room數(shù)據(jù)庫的包裝,快速開發(fā),一行代碼增刪改查

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容