從很早之前就很想要自己搞一個能夠重複使用的儲存架構,但是一直沒有什麼好靈感。直到開始接觸了SQLite,發現它真的是一個小而輕巧的資料庫系統,甚至在移動平台(Android和iOS)中都有內建,才興起了用它當底層來製作儲存架構的念頭。
也許很多人會覺得很奇怪,既然都有SQLite或是其他的資料庫軟體了,為什麼還需要自己做一個儲存架構呢?是自找麻煩嗎?當然不是!有鑑於目前Java程式語言能夠應用在許多地方,像是視窗程式、網頁前端程式或是網頁後端程式,甚至連Android SDK也是用Java語言,但是即使都是Java,在不同應用上程式也都有不同的寫法,彼此間的架構很難重用。而且有時候並不是想要開發一個大專案,而只是想寫一個小小程式儲存一些資料,就要實作龐大的架構出來,使得程式複雜難用又不易除錯,這成本實在是太高了。
ContentCenter
開發資料量不大的小專案,使用ContentCenter是一個不錯的解決方案。ContentCenter實作了部份SQLite的常用功能,甚至可以不必寫到任何一個SQL語法就能輕易建出SQLite的資料庫。ContentCenter另外還結合了Observer,當儲存的資料有改變時,可以更新顯示畫面;也結合了Sync,當本地端或是Server遠端的資料有改變時,可以在彼此間做同步的動作。此外,ContentCenter可以在任意位置存放資料庫檔案,在建立資料庫表格(表單)的時候,還可以提供密鑰指定哪些表單的欄位需要隱藏內容(使用String Hider),大大地提升資料的安全性。
ContentCenter的架構
ContentCenter的底層是SQLite,透過JDBC去連接,用來儲存資料到硬碟。除了ContentCenter外,沒有其他地方可以直接操作到SQLite。實作Observer可用來處理本地端資料改變時,圖形元件的顯示方式;實作Sync可用來處理本地端同步到伺服器端的資料。至於頂層的Application除了可以使用ContentCenter外,還可以不需透過ContentCenter而直接呼叫Sync和Observer,如此在寫程式的時候才不會綁手綁腳,提供了更高的自由度。ContentCenterListener是連結與整合ContentCenter、Sync、Observer和Application之間溝通的重要元件,在初始化ContentCenter前,一定要先將ContentCenterListener在Application內實作出來。
取得ContentCenter
GitHub:
ContentCenter一般使用方式
實作ContentCenterListener
實作ContentCenterListener介面,需要實作以下方法:
public boolean onActionPerforming(EVENT event, NOTIFY notify, JSONObject information) throws Exception;
- event:觸發Listener的事件。共有以下幾種:
- INITIAL_PRAGMA:在ContentCenter執行initialContentCenter方法時,若發現DB檔案並不存在,將會重新建立DB檔案,此時就會以這個事件來通知ContentCenterListener。通常會利用這個事件來決定資料庫要開啟或是關閉的特性。
- INITIAL:在ContentCenter執行initialContentCenter方法時,若發現DB檔案並不存在,將會重新建立DB檔案,此時就會以這個事件來通知ContentCenterListener。通常會利用這個事件來初始化DB的表單。
- AVAILABLE:在ContentCenter執行initialContentCenter方法時,若已經載入好DB檔案,將會進入AVAILABLE狀態,並且以這個事件來通知ContentCenterListener。通常會利用這個事件來先驗證DB的資料。
- INSERT、DELETE、UPDATE:在ContentCenter執行insert、delete或是update方法時,如果需要通知observer或是sync的話,就會以這個事件來通知ContentCenterListener。
- REMOTESYNC:在ContentCenter執行runPeriodicSync方法時,會儘量在一個固定時間不斷以這個事件來通知ContentCenterListener。通常用於檢查遠端資料是否有更變,如果有的話再同步到本地端。
- notify:ContentCenterListener的通知類型。共有以下幾種:
- OBSERVER:通知給Observer。
- SYNC:通知給Sync,使其將本地端更動的資料同步到遠端上。若是REMOTESYNC事件,也會屬於SYNC通知。
- information:ContentCenterListener所傳遞的訊息,用於INSERT、DELETE、UPDATE事件。訊息為JSON格式,其欄位可以使用對應的JSONInsert, JSONDelete, JSONUpdate介面來找到。
初始化ContentCenter
在使用ContentCenter的各項功能之前,必須先初始化ContentCenter。
ContentCenter.initialContentCenter(dbFile, listener, hideKey);
- dbFile:DB的File物件或是路徑。
- listener:實作出來的ContentCenterListener。
- hideKey:欄位隱藏內容所使用的密鑰。沒有設定的話預設不使用密鑰,只是單純的隱藏字串(將可被任何的StringHider解開)。
新增表單(Table)
由於ContentCenter的底層為SQLite,因此在查詢或是更新任何資料時,都是在表單上面操作,因此通常會在ContentCenterListener的INITIAL事件就把ContentCenter的所有表單都通通建好。
ContentCenter.createTable(tableName, metadata);
- tableName:表單名稱。
- metadata:表單描述資料(請參考文件來建立)。
註冊Observer和Sync
ContentCenterListener的REMOTESYNC事件用來處理遠端的資料改變,ContentCenterListener的INSERT、DELETE、UPDATE事件用來處理本地端資料的改變。Observer和Sync專門用來回應本地端資料的改變,因此通常會和INSERT、DELETE、UPDATE合用。如果通知類型為OBSERVER,就使用Observer;如果通知類型為SYNC,就使用Sync。
如果不註冊Observer和Sync物件也是可以完成通知元件更新和同步到遠端的功能,但是當程式跨了好幾個Class時,就會變得十分難用。因此建議在一開始,就把元件更新的方式和同步到遠端的方式事先寫好,註冊到ContentCenter中,以後便可以透過ContentCenter去呼叫。
ContentCenter.registerObserver(observerID, observer);
ContentCenter.registerSync(syncID, sync);
透過自動的ID註冊Observer和Sync後,在ContentCenterListener裡面就可以用notify方法來通知他們進行工作。
ContentCenter.notifyObserver(observerID);
ContentCenter.notifySyncToServer(syncID);
查詢資料
ContentCenter.query(tableName,columnNames,condition,orders);
- tableName:表單名稱。
- columnNames:要保留的欄位名稱(Projection)。
- condition:查詢的條件。
- orders:查詢結果的排序方式。
插入、更新、刪除資料
ContentCenter.insert(tableName,content,notifyObserver,notifySync,notifyID);
ContentCenter.update(tableName,content,condition,notifyObserver,notifySync,notifyID);
ContentCenter.delete(tableName,condition,notifyObserver,notifySync,notifyID);
- tableName:表單名稱。
- content:資料內容。
- condition:比對的條件。
- notifyObserver:是否將更動通知給Observer。
- notifySync:是否將更動通知給Sync。
- notifyID:自訂通知的ID,有助於在ContentCenterListener中辨認通知。預設為時間(毫秒)。
啟動與關閉自動同步
ContentCenterListener的SYNC通知必須由ContentCenter內的PeriodicSync Thread來執行。PeriodicSync會每隔一段時間自動處理遠端和本地端互相同步的相關事項,必須要開啟PeriodicSync,ContentCenterListener才可以接到SYNC通知。
ContentCenter.setSyncPeriod(period);
ContentCenter.runPeriodicSync();
- period: 自動同步的同步週期。(單位為毫秒)
如果要關閉自動同步,使用以下方式。
ContentCenter.stopPeriodicSync();
關閉ContentCenter
由於ContentCenter擁有自己的執行緒,因此若要關閉程式必須先關閉ContentCenter。
ContentCenter.closeContentCenter();
ContentCenter特殊使用方式
User Settings
如果像是要儲存使用者的設定值這種簡單的資料,可以不必另外建立表單,ContentCenter提供put、get、remove方法來快速插入任意字串資料,而且插入資料會被隱藏,如此就不必擔心設定值會外洩。
ContentCenter.put(key,value);
ContentCenter.get(key);
ContentCenter.remove(key);
- key: 資料的key(獨特字串)。
- value: 資料的內容(字串)。
MagicLen Json(Mson)
ContentCenter內建Mson,可以透過Mson快速將物件轉換成JSONObject或是JSONArray。也可以透過Mson將JSONObject或是JSONArray轉換成物件。
MagicStringHider
ContentCenter內建MagicStringHider,可以透過MagicStringHider隱藏儲存在資料庫的資料。