1. 適用範圍
對於什麼情況下才會用到自訂的ContentProvider,官方文檔的Dev Guide是這樣描述的:
如果你想要提供以下的一種或幾種特性的時候你才需要構造一個ContentProvider:
你想要為其它的應用提供複雜的資料或者檔案; 你想允許使用者從你的應用中拷貝複雜的資料到其它的應用中; 你想要使用搜尋方塊架來提供自訂的搜尋策略。
你完全不需要ContentProvider來調用一個SQLite資料庫,如果這種調用完全在你自己的應用之中。
也就是說,ContentProvider的作用是為別的應用調用本應用中的資料或者檔案提供介面,而它也是唯一的跨應用資料傳遞的介面。如果僅僅是同一個應用中的資料傳遞,則完全沒有必要使用到自訂的ContentProvider。
另一方面,雖然ContentProvider也能組織檔案資料或者SharedPreferences(其實也是檔案資料)這種資料,但大多數情況下ContentProvider是作為SQLite資料庫的調用介面來被繼承的。其原因大概是在於重寫的query()方法始終需要返回Cursor,而Cursor作為資料庫資料的容器,並沒有提供直接往Cursor中寫入資料的方法。 2. 大體實現步驟
1. 建立一個資料來源,例如繼承SQLiteOpenHelper建立一個SQLite資料庫;
2. 建立一個繼承自ContentProvider的類,並重寫insert、delete、query、update、getType、onCreate方法,在這些方法中實現對資料來源的操作;
3. 在AndroidManifest.xml檔案中添加<provider>標籤,兩個必寫的屬性是android:name和android:authorities;
4. 在本應用或者其它應用的Activity、Service等組件中使用ContentResolver通過對應的URI來操作該自訂ContentProvider。 3. URI
Android各種類型的URI基本上都是有固定格式的,對於ContentProvider而言,一般形如
content://com.test.cp.MyProvider/phone/1
的URI,其中:
content://是固定欄位,必需;
com.test.cp.MyProvider表示authority,是AndroidManifest.xml檔案中<provider>標籤的android:authorities屬性值,或者是遠端資料源的主機名稱,必需;
phone/1表示path,是資料來源路徑,非必需,其中的phone對於資料庫來說可以視為表名,1表示的是該條資料的編號,如果沒有則一般認為是返回當前路徑(當前表)中的所有資料。
另外還可以根據自己的需要來進一步定義後續的欄位。 4. onCreate方法與構造方法
ContentProvider沒有顯式地執行初始化的語句,因此即便是重寫了它的構造方法也不會被執行。它的初始化代碼一般都寫在onCreate方法中。但是網上的例子中也有部分初始化代碼被寫在了靜態域之中(主要是關於UriMatcher的初始化代碼)。不過經過本人測試發現,把這些放在靜態域中的代碼移到onCreate方法中也不會影響程式的運行。
另外需要注意的是必須把onCreate方法的傳回值該為true,該ContentProvider才能被載入。 5. UriMatch對象
UriMatch對象的作用是將URI匹配到對應的表(就資料庫而言),其使用步驟如下:
1. 通過new UriMatcher(UriMatcher.NO_MATCH); 執行個體化,常量NO_MATCH作為參數表示不匹配任何URI;
2. 執行個體化後調用addURI方法註冊URI,該方法有三個參數,分別需要傳入URI字串的authority部分、path部分以及自訂的整數code三者;
3. 在其它地方調用match方法匹配相應的URI,需要傳入Uri作為唯一的參數,返回上述自訂的code值。
至於其初始化的位置,如前所述,網上絕大多數樣本都將其放入靜態域中執行個體化,原因不明。實際上放到onCreate方法中也沒什麼問題。 6. getType方法
ContentProvider必須重寫的6個方法中,除了初始化方法onCreate以及資料操作的4個方法以外,還有一個getType方法。它的作用是根據URI返回該URI所對應的資料的MIME類型字串。這種字串的格式分為兩段:“A/B”。其中A段是固定的,集合類型(如多條資料)必須是vnd.android.cursor.dir,非集合類型(如單條資料)必須是vnd.android.cursor.item;B段可以是自訂的任一字元串;A、B兩段通過“/”隔開。這個MIME類型字串的作用是要匹配AndroidManifest.xml檔案<activity>標籤下<intent-filter>標籤的子標籤<data>的屬性android:mimeType。如果不一致,則會導致對應的Activity無法啟動。 7. notifyChange方法
網上的某些樣本中在重寫insert、delete、update、query方法對資料的操作結束之後,總會加一句代碼:
getContext().getContentResolver().notifyChange(uri,null);
其作用是通知在ContentResolver中註冊了該URI的ContentObserver,這個URI對應的資料來源發生變化了。其具體用法參見下面的連結:
http://blog.csdn.net/zhf198909/article/details/6903708
另外,通知變化對於ContentProvider來說並不是必需的,根據實際功能的需要,自訂的ContentProvider中多數情況下並不需要這句代碼。 8. 樣本
http://www.cnblogs.com/chenglong/articles/1892029.html