http://blog.csdn.net/sadfishsc/article/details/7419573html
對於什麼狀況下才會用到自定義的ContentProvider,官方文檔的Dev Guide是這樣描述的:android
若是你想要提供如下的一種或幾種特性的時候你才須要構造一個ContentProvider:web
你徹底不須要ContentProvider來調用一個SQLite數據庫,若是這種調用徹底在你本身的應用之中。數據庫
也就是說,ContentProvider的做用是爲別的應用調用本應用中的數據或者文件提供接口,而它也是惟一的跨應用數據傳遞的接口。若是僅僅是同一個應用中的數據傳遞,則徹底沒有必要使用到自定義的ContentProvider。框架
另外一方面,雖然ContentProvider也能組織文件數據或者SharedPreferences(其實也是文件數據)這種數據,但大多數狀況下ContentProvider是做爲SQLite數據庫的調用接口來被繼承的。其緣由大概是在於重寫的query()方法始終須要返回Cursor,而Cursor做爲數據庫數據的容器,並無提供直接往Cursor中寫入數據的方法。ide
1. 建立一個數據源,例如繼承SQLiteOpenHelper建立一個SQLite數據庫;測試
2. 建立一個繼承自ContentProvider的類,並重寫insert、delete、query、update、getType、onCreate方法,在這些方法中實現對數據源的操做;ui
3. 在AndroidManifest.xml文件中添加<provider>標籤,兩個必寫的屬性是android:name和android:authorities;spa
4. 在本應用或者其它應用的Activity、Service等組件中使用ContentResolver經過對應的URI來操做該自定義ContentProvider。.net
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表示的是該條數據的編號,若是沒有則通常認爲是返回當前路徑(當前表)中的全部數據。
另外還能夠根據本身的須要來進一步定義後續的字段。
ContentProvider沒有顯式地執行初始化的語句,所以即使是重寫了它的構造方法也不會被執行。它的初始化代碼通常都寫在onCreate方法中。可是網上的例子中也有部分初始化代碼被寫在了靜態域之中(主要是關於UriMatcher的初始化代碼)。不過通過本人測試發現,把這些放在靜態域中的代碼移到onCreate方法中也不會影響程序的運行。
另外須要注意的是必須把onCreate方法的返回值該爲true,該ContentProvider才能被加載。
UriMatch對象的做用是將URI匹配到對應的表(就數據庫而言),其使用步驟以下:
1. 經過new UriMatcher(UriMatcher.NO_MATCH); 實例化,常量NO_MATCH做爲參數表示不匹配任何URI;
2. 實例化後調用addURI方法註冊URI,該方法有三個參數,分別須要傳入URI字符串的authority部分、path部分以及自定義的整數code三者;
3. 在其它地方調用match方法匹配相應的URI,須要傳入Uri做爲惟一的參數,返回上述自定義的code值。
至於其初始化的位置,如前所述,網上絕大多數示例都將其放入靜態域中實例化,緣由不明。實際上放到onCreate方法中也沒什麼問題。
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沒法啓動。
網上的某些示例中在重寫insert、delete、update、query方法對數據的操做結束以後,總會加一句代碼:
getContext().getContentResolver().notifyChange(uri,null);
其做用是通知在ContentResolver中註冊了該URI的ContentObserver,這個URI對應的數據源發生變化了。其具體用法參見下面的連接:
http://blog.csdn.net/zhf198909/article/details/6903708
另外,通知變化對於ContentProvider來講並非必需的,根據實際功能的須要,自定義的ContentProvider中多數狀況下並不須要這句代碼。