從很早之前就很想要自己搞一個能夠重複使用的儲存架構,但是一直沒有什麼好靈感。直到開始接觸了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轉換成物件。

Mson介紹

MagicStringHider

ContentCenter內建MagicStringHider,可以透過MagicStringHider隱藏儲存在資料庫的資料。

MagicStringHider介紹