本帖最后由 feng_home 于 2010-8-14 08:15 編輯 Android中的Content provider機(jī)制可支持在多個應(yīng)用中存儲和讀取數(shù)據(jù)。這也是跨應(yīng)用共享數(shù)據(jù)的唯一方式。在android系統(tǒng)中,沒有一個公共的內(nèi)存區(qū)域,供多個應(yīng)用共享存儲數(shù)據(jù)。 Android提供了一些主要數(shù)據(jù)類型的Content provider,比如音頻、視頻、圖片和私人通訊錄等。可在android.provider包下面找到一些android提供的Content provider??梢垣@得這些Content provider,查詢它們包含的數(shù)據(jù),當(dāng)然前提是已獲得適當(dāng)?shù)淖x取權(quán)限。 如果想公開自己的數(shù)據(jù),那么可有兩種辦法:
ContentResolver實例帶的方法可實現(xiàn)找到指定的Content provider并獲取到Content provider的數(shù)據(jù)。ContentResolver的查詢過程開始,Android系統(tǒng)將確定查詢所需的具體Content provider,確認(rèn)它是否啟動并運(yùn)行它。android系統(tǒng)負(fù)責(zé)初始化所有的Content provider,不需要用戶自己去創(chuàng)建。實際上,content provider的用戶都不可能直接訪問到content provider實例,只能通過ContentResolver在中間代理。數(shù)據(jù)模型Content provider展示數(shù)據(jù)類似一個單個數(shù)據(jù)庫表。其中:
表示這個uri指定一個content provider。如果你想創(chuàng)建自己的content provider,最好把自定義的URI設(shè)置為類的常量,這樣簡化別人的調(diào)用,并且以后如果更新URI也很容易。android定義了CONTENT_URI常量用于URI,比如:
要注意的是上面例子中的Contacts,已經(jīng)在android 2.0及以上版本不贊成使用。查詢Content provider要想使用一個content provider,需要以下信息:
其中第一個參數(shù)myPerson是Uri類型實例。如果需要查詢的是指定行的記錄,需要用_ID值,比如ID值為23,URI將是類似:
android提供了方便的方法,讓開發(fā)者不需要自己拼接上面這樣的URI,比如類似:
或者:
二者的區(qū)別是一個接收整數(shù)類型的ID值,一個接收字符串類型。其他幾個參數(shù):
返回值的內(nèi)容
和JDBC中不同,沒有直接通過列名獲取列值的方法,只能先列名獲取到列的整型索引值,然后再通過該索引值定位獲取列的值。編輯數(shù)據(jù)可以通過content provider實現(xiàn)以下編輯功能:
在原有記錄上增加值如果記錄已經(jīng)存在,可在記錄上增加新的值,或者編輯已經(jīng)存在的值。首先要過去到原來的值對象,然后要清除原有的值,然后像上面增加記錄一樣即可:
批量更新值批量更新一組記錄的值,比如NY改名為Eew York??烧{(diào)用ContenResolver.update()方法。刪除記錄如果是刪除單個記錄,調(diào)用ContentResolver.delete()方法,URI參數(shù),指定到具體行即可。如果是刪除多個記錄,調(diào)用ContentResolver.delete()方法,URI參數(shù)指定Content provider即可,并帶一個類似SQL的WHERE子句條件。這里和上面類似,不帶WHERE關(guān)鍵字。創(chuàng)建自己的Content provider創(chuàng)建content provider,需要:
insert() update() delete() getType() onCreate()query()方法,返回值是Cursor實例,用于迭代請求的數(shù)據(jù)。Cursor是一個接口。android為該接口提供了一些只讀的(和JDBC的ResultSet不一樣,后者還提供可寫入的可選特性)Cursor實現(xiàn)。比如SQLiteCursor,可迭代SQLite數(shù)據(jù)庫中的數(shù)據(jù)。可以通過SQLiteDatabase類的query()方法獲取到該Cursor實例。還有其他的Cursor實現(xiàn),比如MatrixCursor,用于數(shù)據(jù)不是存儲在數(shù)據(jù)庫的情況下。因為Content provider可能被多個ContentResolver對象在不同的進(jìn)程和線程中調(diào)用,因此實現(xiàn)Content provider必須考慮線程安全問題。作為良好的習(xí)慣,在實現(xiàn)編輯數(shù)據(jù)的代碼中,要調(diào)用ContentResolver.notifyChange()方法,通知那些監(jiān)聽數(shù)據(jù)變化的監(jiān)聽器。在實現(xiàn)子類的時候,還有一些步驟可以簡化Content provider客戶端的使用:定義public static final Uri常量,名稱為CONTENT_URI:
如果有多個表,它們也是使用相同的CONTENT_URI,只是它們的路徑部分不同。 也就是說紅色框部分是一致的。定義返回的列名,public static final,列名的值,比如使用SQLite數(shù)據(jù)庫作為存儲,對應(yīng)表的列名。在文檔中要寫出各個列的數(shù)據(jù)類型,便于使用者讀取。如果需要處理新的MIME數(shù)據(jù)類型,比如通過Intent的方式,并且?guī)ata的mimeType,那么需要在ContentProvider.getType()方法中進(jìn)行處理。聲明Content Provider創(chuàng)建Content Provider后,需要在manifest文件中聲明,android系統(tǒng)才能知道它,當(dāng)其他應(yīng)用需要調(diào)用該Content Provider時才能創(chuàng)建或者調(diào)用它。語法類似:
android:name要寫ContentProvider繼承類的全名。android:authorities要寫和CONTENT_URI常量的B部分(見上面圖)。注意不要把上圖C和D部分加到authorities中去。authorities是用來識別ContentProvider的,C和D部分實際上是ContentProvider內(nèi)部使用的。 |
聯(lián)系客服