本節書摘來自異步社群《android 3d遊戲開發技術寶典——opengl es 2.0》一書中的第2章,第2.3節手機自帶資料庫——sqlite,作者 吳亞峰,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視
2.3 手機自帶資料庫——sqlite
android 3d遊戲開發技術寶典——opengl es 2.0
上一節介紹了如何使用preferences存儲簡單資料,而複雜的資料就需要存儲到檔案或資料庫中了。 android自帶了一款輕量級的關系資料庫——sqlite,其具有體積小,功能強大等諸多特點,成為嵌入式裝置首選的資料庫系統。本節将帶領讀者走進sqlite的世界,去學習如何應用sqlite資料庫進行資料的增、删、改、查等基本操作。
2.3.1 初識sqlite
sqlite是一款滿足acid特性的具有完備功能的關系資料庫系統,由于其設計目标為輕量級、開源、支援嵌入式使用,是以,目前已經在嵌入式裝置領域被廣泛采用。其運作需要的系統資源非常少,在嵌入式裝置中可能隻需要幾百kb的記憶體就夠了。
sqlite對主流程式設計語言的支援也非常全面,如c#、php、java等,同時還支援odbc接口。另外,sqlite的性能也是一流的,在一般應用情況下,其處理速度比mysql、postgresql這兩款著名的開源資料庫管理系統都快。
雖然sqlite占用的資源非常少,但是其功能、特性與伺服器級資料庫相比卻絲毫不差,這也是sqlite能夠受到android系統青睐的主要原因,其部分特性如下所列。
最大可以支援2tb的資料庫檔案。
占用資源少,一般占用250kb左右。
api非常簡單,易于使用。
沒有任何額外的依賴,是獨立的。
源代碼完全開放,可以用于任何用途。
android系統中很多的使用者資料都是存儲在sqlite資料庫中的,如聯系人資訊、通話記錄、短信等,由此可見sqlite對于android的重要性。
提示 讀者要想很好地使用sqlite資料庫,必須熟練掌握sql語言。這是由于sql已經事實上成為關系資料庫操作的标準語言,市面上的關系資料庫幾乎無一例外都支援sql。是以在資料庫領域,有這樣一句話“學好sql,走遍天下都不怕”。
2.3.2 sqlite資料庫的基本操作
一般學習資料庫相關課程的時候,首先介紹的就是資料庫的一些基本操作,如資料的增、删、改、查等。按照慣例,本書也首先簡單介紹sqlite資料庫的建立、關閉及資料的增加、删除、修改、查詢等基本操作,具體如下所列。
提示 想在android下通過java程式設計對sqlite資料庫進行操作,就必須要用到android.database.sqlite包下的sqlitedatabase類,該類提供了對sqlite資料庫進行基本操作的所有重要方法。
建立資料庫。
建立資料庫需要用到的是opendatabase方法,此方法簽名為“public static sqlitedatabase opendatabase (string path, sqlitedatabase.cursorfactory factory, int flags)”。其中path為資料庫所在的路徑;factory為遊标工廠;flags為标志,可以用來控制資料庫的通路模式。
關閉資料庫。
關閉資料庫需要用到的是close方法,此方法簽名為“public void close()”。在實際開發中資料庫使用完畢後,一定不要忘記使用該方法關閉資料庫,以防止資源的浪費。
插入資料。
插入資料可以使用insert方法,此方法簽名為“public long insert (string table, string nullcolumnhack, contentvalues values)”。其中table為待插入的表名,nullcolumnhack通常設定為null,values為待插入的資料。
更新資料。
更新資料可以使用update方法,其簽名為“public int update(string table, contentvalues values, string whereclause, string[] whereargs)”。其中table為待更新的表名;values為待更新内容;whereclause為where子句的内容,用來進行記錄篩選;whereargs為where子句的參數。
删除資料。
删除資料可以使用delete方法,其簽名為“public int delete (string table, string whereclause, string[] whereargs)”。其中table為要操作的表名;whereclause為where子句的内容,用來進行記錄篩選;whereargs為where子句的參數。
查詢資料。
查詢資料可以使用query方法,其方法簽名為“public cursor query (string table, string[] columns, string selection, string[] selectionargs, string groupby, string having, string orderby)”。其中table為要查詢的表,columns為要查詢的列,selection為過濾記錄的子句,selectionargs為過濾的參數值,groupby為分組子句,having為過濾分組的子句,orderby為記錄排序子句。
提示 android中query方法被重載了,有多個變體。這裡由于篇幅所限,不再贅述,有需要的讀者可以自行查閱api或其他相關資料。
執行非查詢sql。
對于不太熟悉sql語言的初學者而言,插入、更新、删除資料可以用前面介紹的insert、update、delete方法。但對于熟練掌握sql的開發人員而言,就是使用execsql方法直接執行相應的sql語句更友善了。
此方法簽名為“public void execsql (string sql)”或“public void execsql (string sql, object[] bindargs)”。其中sql為需要執行的sql語句,bindargs為帶參數sql語句的參數值數組。
提示 需要注意的是,此方法僅支援執行非查詢的sql語句,如create table、 delete、 insert、update等,不能用于執行select語句。
執行查詢sql。
對于熟練掌握sql的開發人員而言,會覺得前面介紹的query方法使用過于煩瑣。android的設計人員也考慮到了這個問題,提供了支援執行查詢sql語句的rawquery方法,其方法簽名為“public cursor rawquery (string sql, string[] selectionargs)”。其中sql為要執行的查詢sql語句(可以帶參數),selectionargs為查詢參數的值。
提示 sqlitedatabase類中用于資料庫操作的方法還有很多,本書隻是介紹了其中一些常用的,若讀者有需要可以查閱api或其他相關資料進一步學習。
2.3.3 sqlite資料庫的簡單案例
上一小節介紹了sqlite資料庫的基本操作方法,本小節将詳細介紹一個使用sqlite資料庫的簡單案例,以使讀者可以更加快速地掌握sqlite資料庫的使用方法,進而在開發中進行合理地使用。本案例運作效果分别如圖2-10、圖2-11和圖2-12所示。

介紹完本案例的運作效果後,接下來将開發本案例中唯一的一個類——sample2_4_activity,其代碼如下。
第10-40行為案例中的各個按鈕添加監聽器,監聽器中調用對應的方法來實作資料庫的打 開/建立、關閉、插入、删除和查詢等操作。
第41-58行為建立及打開資料庫的方法,方法中首先擷取了sqlitedatabase對象的引用,并為其指定資料庫的存儲路徑和讀寫模式,然後用“create table”語句來建立了一張名稱為student的表。
第67-76行為向資料庫中插入一條記錄的方法,插入的記錄内容為“‘001’,‘android’,22,‘283’”。
第77-85行為删除資料庫中所有記錄的方法。
第86-104行為從資料庫中查找符合條件記錄的方法,首先需要擷取cursor對象的引用,并為其添加查找範圍(具體範圍為年齡大于20)。若查到相應記錄,則将記錄資訊用toast顯示出來。
2.3.4 使用contentprovider元件共享資料
前一小節介紹了sqlite資料庫中的一些操作,但有時資料庫中的資訊不但建立其的應用程式要使用,還希望能夠分享給其他應用程式使用。這時就需要使用contentprovider元件了,contentprovider元件的基本情況如下所列。
android平台中每個應用程式都有自己的使用者id并在自己的程序中運作,每個程序擁有獨立的運作環境,這樣可以保證程式的完整性。但這也使得應用程式在需要進行資源共享和資料通信時,很不友善。為了解決這一問題,android提供了專門用來在應用程式之間分享資料的contentprovider元件。
contentprovider能将應用程式中特定的資料提供給其他應用程式使用,這些資料可以來自應用程式私有檔案夾下的私有資料檔案,也可以來自應用程式自己私有的sqlite資料庫。當然,資料的來源還有很多其他選擇,contentprovider元件本身并沒有做出限制,讀者可以充分發揮想象的空間。
使用contentprovider元件共享資料的基本方式是繼承contentprovider類并重寫其中的相應方法,具體情況在後面的案例中進行介紹。
别的應用程式想分享資料時需要使用contentresolver,通過contentresolver對象将分享的需求發送給contentprovider元件,而不能直接調用contentprovider元件。
下面使用contentprovider元件将上一小節的案例進行更新,使得此案例具有分享資料給其他應用程式的能力,其具體開發步驟如下。
(1)在案例sample2_4的com/bn/pp4包下建立mycontentprovider類,該類繼承自contentprovider類,并要實作其中所有的抽象方法,具體代碼如下。
第6-10行為聲明uri比對對象,并且設定比對字元串。此比對字元串在需要得到分享資料的應用程式中提供給contentresolver使用,以進行配對。
第12-14行重寫了gettype方法,本案例中對gettype方法沒有要求,是以其傳回空值。
第16-25行重寫了query方法,在比對成功後,資料需求方通過contentresolver調用此方法查詢需要的資料。
第26-31行重寫了delete與insert方法,本案例中對這兩個方法沒有要求,是以都設定為傳回空值。
第32-40行重寫了oncreate方法,其功能為首先擷取sqlitedatabase對象引用,然後建立或打開資料庫,為資訊的分享做好準備。
第41-44行重寫了update方法,本案例中對這個方法沒有要求,是以設定為傳回空值。
(2)僅僅是完成上面的代碼還是不夠的,在android程式開發中,有一個很重要的配置檔案androidmanifest.xml。要想使用contentprovider元件,在完成代碼的開發後,還必須在該配置檔案中進行相應的配置,将如下代碼插入到androidmanifest.xml檔案中的application标簽中。
2.3.5 使用contentresolver擷取分享資料
更新完了sample2_4使其具有了資料分享能力之後,就可以在别的應用程式中通過contentresolver比對到sample2_4案例中的contentprovider元件擷取分享的資料了。具體的開發步驟如下所列。
(1)建立項目sample2_4_from,将項目的包名設定為com.bn.pp4f,并建立一個繼承自activity的類contentconsumeractivity,其代碼如下。
第8-25行主要功能為擷取contentresolver對象的引用,并給按鈕添加監聽器,使得按鈕按下後可以通過contentresolver比對到sample2_4案例中的contentprovider元件擷取需要的資料。
第26-33行功能為将擷取的sample2_4案例分享的資料顯示到螢幕上的edittext控件中。
第35-38行為向edittext控件中添加文本資訊的方法。
(2)sample2_4_from案例開發完成後,運作該案例,其效果如圖2-13、圖2-14所示。
說明 圖2-13為運作該案例後的界面效果圖,圖2-14為單擊“擷取”按鈕後,通過contentresolver比對到sample2_4案例中的contentprovider元件擷取資料後的效果圖。