<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                1. SQLite輕裝上陣 SQLite是一個輕量級的數據庫,它和筆者之前接觸的SQLServer或Oracle DB比起來,猶如螞蟻和大象的區別。它“輕”到什么程度呢?筆者總結了SQLite具有的兩個特點: - 從代碼上看,SQLite所有的功能都實現在Sqlite3.c中,而頭文件Sqlite3.h定義了它所支持的API。其中,Sqlite3.c文件包含12萬行左右的代碼,相當于一個中等偏小規模的程序。 - 從使用者角度的來說,SQLite編譯完成后將生成一個libsqlite.so,大小僅為300多KB。 SQLite確實夠輕,但這個“輕”還不是本節標題“輕裝上陣”一詞中的“輕”。為什么?此處先向讀者們介紹一個直接使用SQLite API開發的Android native程序示例,該示例最終編譯成的二進制可執行程序名為sqlitetest。 >[info] **注意**:本書后文所說的SQLite API特指libsqlite.so提供的Native層的API。 使用SQLite API開發的Android native程序示例的代碼如下: **SqliteTest.cpp::libsqlite示例** ~~~ #include <unistd.h> #include <sqlite3.h> //包含sqlite API頭文件,這里的3是SQLite的版本號 #include <stdlib.h> #define LOG_TAG "SQLITE_TEST" //定義該進程logcat輸出的標簽 #include <utils/Log.h> #ifndef NULL #defineNULL (0) #endif //聲明數據庫文件的路徑 #define DB_PATH"/mnt/sdcard/sqlite3test.db" /* 聲明一個全局的SQLite句柄,開發者無需了解該數據結構的具體內容,只要知道它代表了使用者 和數據庫的一種連接關系即可。以后凡是針對特定數據庫的操作,都需要傳入對應的SQLite句柄 */ static sqlite3* g_pDBHandle = NULL; /* 定義一個宏,用于檢測SQLite API調用的返回值,如果value不等于expectValue,則打印警告, 并退出程序。注意,進程退出后,系統會自動回收分配的內存資源。對如此簡單的例子來說,讀者大可 不必苛責。其中,sqlite3_errmsg函數用于打印錯誤信息 */ #define CHECK_DB_ERR(value,expectValue) \ do \ { \ if(value!= expectValue)\ {\ LOGE("Sqlite db fail:%s",g_pDBHandle==NULL?"db not \ connected":sqlite3_errmsg(g_pDBHandle));\ exit(0);\ }\ }while(0) int main(int argc, char* argv[]) { LOGD("Delete old DB file"); unlink(DB_PATH);//先刪除舊的數據庫文件 LOGD("Create new DB file"); /* 調用sqlite3_open創建一個數據庫,并將和該數據庫的連接環境保存在全局的SQLite句柄 g_pDBHandle中,以后操作g_pDBHandle就是操作DB_PATH對應的數據庫 */ int ret =sqlite3_open(DB_PATH,&g_pDBHandle); CHECK_DB_ERR(ret,SQLITE_OK); LOGD("Create Table personal_info:"); /* 定義宏TABLE_PERSONAL_INFO,用于描述為本例數據庫建立一個表所用的SQL語句, 不熟悉SQL語句的讀者可先學習相關知識。從該宏的定義可知,將建立一個名為 personal_info的表,該表有4列,第一列是主鍵,類型是整型(SQLite中為INTEGER), 每加入一行數據該值會自動遞增;第二列名為"name",數據類型是字符串(SQLite中為TEXT); 第三列名為“age”,數據類型是整型;第四列名為“sex”,數據類型是字符串 */ #defineTABLE_PERSONAL_INFO \ "CREATETABLE personal_info" \ "(ID INTEGER primary keyautoincrement," \ "nameTEXT," \ "age INTEGER,"\ "sex TEXT"\ ")" //打印TABLE_PERSONAL_INFO所對應的SQL語句 LOGD("\t%s\n",TABLE_PERSONAL_INFO); //調用sqlite3_exec執行前面那條SQL語句 ret =sqlite3_exec(g_pDBHandle,TABLE_PERSONAL_INFO,NULL,NULL,NULL); CHECK_DB_ERR(ret,SQLITE_OK); /* 定義插入一行數據所使用的SQL語句,注意最后一行中的問號,它表示需要在插入數據 前和具體的值綁定。插入數據庫對應的SQL語句是標準的INSERT命令 */ LOGD("Insert one personal info into personal_info table"); #defineINSERT_PERSONAL_INFO \ "INSERT INTO personal_info"\ "(name,age,sex)"\ "VALUES"\ "(?,?,?)" //注意這一行語句中的問號 LOGD("\t%s\n",INSERT_PERSONAL_INFO); //sqlite3_stmt是SQLite中很重要的一個結構體,它代表了一條SQL語句 sqlite3_stmt* pstmt = NULL; /* 調用sqlite3_prepare初始化pstmt,并將其和INSERT_PERSONAL_INFO綁定。 也就是說,如果執行pstmt,就會執行INSERT_PERSONAL_INFO語句 */ ret =sqlite3_prepare(g_pDBHandle,INSERT_PERSONAL_INFO,-1,&pstmt,NULL); CHECK_DB_ERR(ret,SQLITE_OK); /* 調用sqlite3_bind_xxx為該pstmt中對應的問號綁定具體的值,該函數的第二個參數用于 指定第幾個問號 */ ret =sqlite3_bind_text(pstmt,1,"dengfanping",-1,SQLITE_STATIC); ret =sqlite3_bind_int(pstmt,2,30); ret =sqlite3_bind_text(pstmt,3,"male",-1,SQLITE_STATIC); //調用sqlite3_step執行對應的SQL語句,該函數如果執行成功,我們的personal_info //表中將添加一條新記錄,對應值為(1,dengfanping,30,male) ret =sqlite3_step(pstmt); CHECK_DB_ERR(ret,SQLITE_DONE); //調用sqlite3_finalize銷毀該SQL語句 ret =sqlite3_finalize(pstmt); //下面將從表中查詢name為"dengfanping"的person的age值 LOGD("select dengfanping's age from personal_info table"); pstmt =NULL; /* 重新初始化該pstmt,并將其和SQL語句“SELECT age FROM personal_info WHERE name = ?”綁定 */ ret =sqlite3_prepare(g_pDBHandle,"SELECT age FROM personal_info WHERE name =? ",-1,&pstmt,NULL); CHECK_DB_ERR(ret,SQLITE_OK); /* 綁定pstmt中第一個問號為字符串“dengfanping”,最終該SQL語句為 SELECTage FROM personal_info WHERE name = 'dengfanping' */ ret =sqlite3_bind_text(pstmt,1,"dengfanping",-1,SQLITE_STATIC); CHECK_DB_ERR(ret,SQLITE_OK); //執行這條查詢語句 while(true)//在一個循環中遍歷結果集 { ret =sqlite3_step(pstmt); if(ret ==SQLITE_ROW) { //從結果集中取出第一列(由于執行SELECT時只選擇了age,故最終結果只有一列), //調用sqlite3_column_int返回結果集的第一列(從0開始)第一行的值 intmyage = sqlite3_column_int(pstmt, 0); LOGD("Gotdengfanping's age: %d\n",myage); } else //如果ret為其他值,則退出循環 break; } else LOGD("Find nothing\n"); //SELECT執行失敗 ret =sqlite3_finalize(pstmt);//銷毀pstmt if(g_pDBHandle) { LOGD("CloseDB"); //調用sqlite3_close關閉數據庫連接并釋放g_pDBHandle sqlite3_close(g_pDBHandle); g_pDBHandle = NULL; } return 0; } ~~~ 通過上述示例代碼可發現,SQLite API的使用主要集中在以下幾點上: - 創建代表指定數據庫的sqlite3實例。 - 創建代表一條SQL語句的sqlite3_stmt實例,在使用過程中首先要調用sqlite3_prepare將其和一條代表SQL語句的字符串綁定。如該字符串含有通配符“?”,后續就需要通過sqlite3_bind_xxx函數為通配符綁定特定的值以生成一條完整的SQL語句。最終調用sqlite3_step執行這條語句。 - 如果是查詢(即SELECT命令)命令,則需調用sqlite3_step函數遍歷結果集,并通過sqlite3_column_xx等函數取出結果集中某一行指定列的值。 - 最后需調用sqlite3_finalize和sqlite3_close來釋放sqlite3_stmt實例及sqlite3實例所占據的資源。 SQLite API的使用非常簡單明了。不過很可惜,這份簡單明了所帶來的快捷,只供那些Native層程序開發者獨享。對于Java程序員,他們只能使用Android在SQLite API之上所封裝的SQLiteDatabase家族提供的類和相關API。筆者心中對這個封裝的評價只有一個詞 “嘆為觀止”,綜合考慮到架構及系統的穩定性和可擴展性等各種情況,Android在 SQLite API之上進行了面向對象的封裝和解耦等設計,最終呈現在大家面前的是一個龐大而復雜的SQLiteDatabase家族,其成員有61個之多(參閱frameworks/base/core/java/android/database目錄中的文件)。 現在讀者應該理解本節標題“SQLite輕裝上陣”中“輕”的真正含義了。在后續的分析過程中,我們主要和SQLiteDatabase家族打交道。隨著分析的深入,讀者能逐漸見認識SQLiteDatabase的“厚重"。 2. SQLiteDatabase家族介紹 圖7-4展示了SQLiteDatabase家族中的幾位重要成員。 :-: ![](http://img.blog.csdn.net/20150803130857498?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖7-4 SQLitDatabase家族部分成員 圖7-4中相關類的說明如下: - SQLiteOpenHelper是一個幫助(Utility)類,用于方便開發者創建和管理數據庫。 - SQLiteQueryBuilder是一個幫助類,用于幫助開發者創建SQL語句。 - SQLiteDatabase代表SQLite數據庫,它內部封裝了一個Native層的sqlite3實例。 - Android提供了3個類SQLiteProgram、SQLiteQuery和SQLiteStatement用于描述和SQL語句相關的信息。從圖7-4可知,SQLiteProgram是基類,它提供了一些API用于參數綁定。SQLiteQuery主要用于query查詢操作,而SQLiteStatement用于query之外的一些操作(根據SDK的說明,如果SQLiteStatement用于query查詢,其返回的結果集只能是1行*1列)。注意,在這3個類中,基類SQLiteProgram將保存一個指向Native層的sqlite3_stmt實例的變量,但是這個成員變量的賦值卻和另外一個對開發者隱藏的類SQLiteComplieSql有關。從這個角度看,可以認為Native層sqlite3_stmt實例的封裝是由SQLiteComplieSql完成的。這方面的知識在后文進行分析時即能見到。 - SQLiteClosable用于控制SQLiteDatabase家族中一些類的實例的生命周期,例如SQLiteDatabase實例和SQLiteQuery實例。每次使用這些實例對象前都需要調用acquireReference以增加引用計數,使用完畢后都需要調用releaseReferenece以減少引用計數。 * * * * * **提示**:讀者見識了SQLiteDatabase家族中這幾位成員后有何感想?是否覺得要真正搞清楚它們還需要花費一番工夫呢? * * * * * 下面來看MediaProvider是如何使用SQLiteDatabase的,重點關注SQLite數據庫是如何創建的。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看