本文目的在于,針對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地址:
一.下面我們來看一下原生的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的訂閱。