官术网_书友最值得收藏!

4.5 內(nèi)容提供與處理

本節(jié)介紹Android四大組件之一的ContentProvider的基本概念和常見用法。首先說明如何使用內(nèi)容提供器封裝數(shù)據(jù)的外部訪問接口;接著闡述如何通過內(nèi)容解析器在外部查詢和修改數(shù)據(jù),以及使用內(nèi)容操作器完成批量數(shù)據(jù)操作;然后說明內(nèi)容觀察器的應(yīng)用場合,并演示如何借助內(nèi)容觀察器實現(xiàn)流量校準的功能。

4.5.1 內(nèi)容提供器ContentProvider

Android號稱提供了4大組件,分別是頁面Activity、廣播Broadcast、服務(wù)Service和內(nèi)容提供器ContentProvider。其中內(nèi)容提供器是跟數(shù)據(jù)存取有關(guān)的組件,完整的內(nèi)容組件由內(nèi)容提供器ContentProvider、內(nèi)容解析器ContentResolver、內(nèi)容觀察器ContentObserver這三部分組成。

ContentProvider為App存取內(nèi)部數(shù)據(jù)提供統(tǒng)一的外部接口,讓不同的應(yīng)用之間得以共享數(shù)據(jù)。像我們熟知的SQLite操作的是應(yīng)用自身的內(nèi)部數(shù)據(jù)庫;文件的上傳和下載操作的是后端服務(wù)器的文件;而ContentProvider操作的是本設(shè)備其他應(yīng)用的內(nèi)部數(shù)據(jù),是一種中間層次的數(shù)據(jù)存儲形式。

在實際編碼中,ContentProvider只是一個服務(wù)端的數(shù)據(jù)存取接口,開發(fā)者需要在其基礎(chǔ)上實現(xiàn)一個具體類,并重寫以下相關(guān)數(shù)據(jù)庫管理方法。

  • onCreate:創(chuàng)建數(shù)據(jù)庫并獲得數(shù)據(jù)庫連接。
  • query:查詢數(shù)據(jù)。
  • insert:插入數(shù)據(jù)。
  • update:更新數(shù)據(jù)。
  • delete:刪除數(shù)據(jù)。
  • getType:獲取數(shù)據(jù)類型。

這些方法看起來是不是很像SQLite?沒錯,ContentProvider作為中間接口,本身并不直接保存數(shù)據(jù),而是通過SQLiteOpenHelper與SQLiteDatabase間接操作底層的SQLite。所以要想使用ContentProvider,首先得實現(xiàn)SQLite的數(shù)據(jù)表幫助類,然后由ContentProvider封裝對外的接口。

下面是使用ContentProvider提供用戶信息對外接口的代碼:

既然內(nèi)容提供器是四大組件之一,就得在AndroidManifest.xml中注冊它的定義,并開放外部訪問權(quán)限,注冊代碼如下:

注冊完畢后就完成了服務(wù)端App的封裝工作,接下來可由其他App進行數(shù)據(jù)存取。

4.5.2 內(nèi)容解析器ContentResolver

前面提到了利用ContentProvider實現(xiàn)服務(wù)端App的數(shù)據(jù)封裝,如果客戶端App想訪問對方的內(nèi)部數(shù)據(jù),就要通過內(nèi)容解析器ContentResolver訪問。內(nèi)容解析器是客戶端App操作服務(wù)端數(shù)據(jù)的工具,相對應(yīng)的內(nèi)容提供器是服務(wù)端的數(shù)據(jù)接口。要獲取ContentResolver對象,在Activity代碼中調(diào)用getContentResolver方法即可。

ContentResolver提供的方法與ContentProvider是一一對應(yīng)的,比如query、insert、update、delete、getType等方法,連方法的參數(shù)類型都一模一樣。其中,最常用的是query函數(shù),調(diào)用該函數(shù)返回一個游標Cursor對象,這個游標與SQLite的游標是一樣的,想必讀者早已用得爐火純青。

下面是query方法的具體參數(shù)說明(依順序排列)。

  • uri:Uri類型,可以理解為本次操作的數(shù)據(jù)表路徑。
  • projection:字符串?dāng)?shù)組類型,指定將要查詢的字段名稱列表。
  • selection:字符串類型,指定查詢條件。
  • selectionArgs:字符串?dāng)?shù)組類型,指定查詢條件中的參數(shù)取值列表。
  • sortOrder:字符串類型,指定排序條件。

針對前面UserInfoProvider提供的數(shù)據(jù)接口,下面使用ContentResolver在客戶端添加用戶信息,代碼如下:

下面是使用ContentResolver在客戶端查詢所有用戶信息的代碼:

添加用戶信息的效果如圖4-19所示,一開始服務(wù)端的用戶表不存在用戶記錄,客戶端使用ContentResolver添加一條記錄后,服務(wù)端的用戶記錄數(shù)返回1。用戶信息的查詢明細如圖4-20所示,點擊頁面上的用戶記錄數(shù)量文字,彈出一個對話框,提示當(dāng)前找到的所有用戶的明細數(shù)據(jù),包括姓名、年齡、身高、體重等信息。

圖4-19 利用內(nèi)容提供器添加用戶信息

圖4-20 利用內(nèi)容解析器查詢獲得用戶信息

在實際開發(fā)中,普通App很少會開放數(shù)據(jù)接口給其他應(yīng)用訪問,作為服務(wù)端接口的ContentProvider基本用不到。內(nèi)容組件能夠派上用場的情況往往是App想要訪問系統(tǒng)應(yīng)用的通信數(shù)據(jù),比如查看聯(lián)系人、短信、通話記錄,以及對這些通信信息進行增、刪、改、查。

下面是使用ContentResolver添加聯(lián)系人信息的代碼片段,此時訪問的數(shù)據(jù)來源變成了系統(tǒng)自帶的raw_contacts:

注意上述代碼用了4條insert語句,但業(yè)務(wù)上只添加了一個聯(lián)系人信息。這樣處理有一個問題,就是4個insert操作不在同一個事務(wù)中,要是中間某步insert操作失敗,那么之前插入成功的記錄就無法自動回滾,從而產(chǎn)生垃圾數(shù)據(jù)。

為了避免這種情況的發(fā)生,Android提供了內(nèi)容操作器ContentProviderOperation進行批量數(shù)據(jù)的處理,即在一個請求中封裝多條記錄的修改動作,然后一次性提交給服務(wù)端,從而實現(xiàn)在一個事務(wù)中完成多條數(shù)據(jù)的更新操作。即使某條記錄處理失敗,ContentProviderOperation也能根據(jù)事務(wù)一致性原則自動回滾本事務(wù)已經(jīng)執(zhí)行的修改操作。

下面是使用ContentProviderOperation批量添加聯(lián)系人信息的代碼片段:

添加聯(lián)系人信息的效果如圖4-21和圖4-22所示。其中,圖4-21所示為添加之前的截圖,此時聯(lián)系人個數(shù)為157位;圖4-22所示為添加成功之后的截圖,此時聯(lián)系人個數(shù)為158位。

圖4-21 聯(lián)系人添加之前的界面

圖4-22 聯(lián)系人添加之后的界面

4.5.3 內(nèi)容觀察器ContentObserver

ContentResolver獲取數(shù)據(jù)采用的是主動查詢方式,有查詢就有數(shù)據(jù),沒查詢就沒數(shù)據(jù)。有時我們不但要獲取以往的數(shù)據(jù),還要實時獲取新增的數(shù)據(jù),最常見的業(yè)務(wù)場景是短信驗證碼。電商App經(jīng)常在用戶注冊或付款時發(fā)送驗證碼短信,為了給用戶省事,App通常會監(jiān)控手機剛收到的驗證碼數(shù)字,并自動填入驗證碼輸入框。這時就用到了內(nèi)容觀察器ContentObserver,給目標內(nèi)容注冊一個觀察器,目標內(nèi)容的數(shù)據(jù)一旦發(fā)生變化,觀察器規(guī)定好的動作馬上觸發(fā),從而執(zhí)行開發(fā)者預(yù)先定義的代碼。

內(nèi)容觀察器的用法與內(nèi)容提供器類似,也要從ContentObserver派生一個觀察器類,然后通過ContentResolver對象調(diào)用相應(yīng)的方法注冊或注銷觀察器。下面是ContentResolver與觀察器有關(guān)的方法說明。

  • registerContentObserver:注冊內(nèi)容觀察器。
  • unregisterContentObserver:注銷內(nèi)容觀察器。
  • notifyChange:通知內(nèi)容觀察器發(fā)生了數(shù)據(jù)變化。

為了讓讀者更好理解,下面舉一個實際應(yīng)用的例子。手機號碼的每月流量限額一般由用戶手動配置,但流量限額其實是由移動運營商指定的。以中國移動為例,只要發(fā)送流量校準短信給運營商客服號碼(如發(fā)送18到10086),運營商就會給用戶發(fā)送本月的流量數(shù)據(jù),包括月流量額度、已使用流量、未使用流量等信息。手機App只需監(jiān)控10086發(fā)送的短信內(nèi)容,即可自動獲取手機號碼的月流量額度,無須用戶手工配置。

下面是利用ContentObserver實現(xiàn)流量校準的代碼片段:

流量校準的效果如圖4-23和圖4-24所示。其中,圖4-23所示為用戶實際收到的短信內(nèi)容,圖4-24所示為App監(jiān)視短信并解析完成的流量數(shù)據(jù)頁面。

圖4-23 用戶收到的短信內(nèi)容

圖4-24 內(nèi)容觀察器監(jiān)視并解析得到的流量信息

總結(jié)一下在Content組件經(jīng)常使用的系統(tǒng)URI,詳細的URI取值說明見表4-3。

表4-3 常用的系統(tǒng)URI取值說明

主站蜘蛛池模板: 敖汉旗| 巫溪县| 永济市| 习水县| 寿阳县| 阿克陶县| 青川县| 密云县| 韶山市| 聂拉木县| 枝江市| 西乌| 咸宁市| 松江区| 普兰县| 江津市| 惠水县| 江西省| 铜山县| 永州市| 莱芜市| 德保县| 武鸣县| 象山县| 津南区| 迭部县| 克拉玛依市| 措美县| 尖扎县| 琼中| 瓮安县| 陇南市| 襄汾县| 贺兰县| 清河县| 都匀市| 郓城县| 海原县| 友谊县| 南雄市| 奇台县|