ContentProvider使用詳解

1、使用ContentProvider共享數據

ContentProvider在Android中的做用是對外提供數據,除了能夠爲所在應用提供
數據外,還能夠共享數據給其餘應用,這是Android中解決應用之間數據共享的
機制。經過ContentProvider咱們能夠對數據進行增刪改查的操做。當應用須要
經過ContentProvider對外共享數據時,具體做法以下: android

一、 繼承系統ContentProvider,並重寫如下方法

  1. public class PersonContentProvider extends ContentProvider{   
  2.    public boolean onCreate()   
  3.    public Uri insert(Uri uri, ContentValues values)   
  4.    public int delete(Uri uri, String selection, String[] selectionArgs)   
  5.    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)   
  6.    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)   
  7.    public String getType(Uri uri)   
  8. }   

在重寫這些方法時,根據所採用的數據存儲方式進行相應修改。一般使用的
是SQLite數據庫存儲,咱們須要新建數據庫操做類,並在增刪改查方法中完
成對數據庫的操做。git

二、 須要在AndroidManifest.xml文件中註冊咱們的ContentProvider,這樣系統方

法context.getContentResolver()才能找到咱們重寫的ContentProvider。在注
冊ContentProvider時,採用了authorities(主機名/域名)的方法對它進行
惟一標識,ContentProvider的標識相似於網站的域名,經過此域名咱們能夠
準確訪問到對應網站,網站爲咱們提供數據。Authorities就是ContentProvider
的域名。註冊方法以下:github

  1. <manifest.... >   
  2.    <application android:icon="@drawable/icon" android:label="@string/app_name">   
  3.       <provider android:name=".PersonContentProvider"    
  4.            android:authorities="com.ljq.providers.personprovider"/>   
  5.    </application>   
  6. </manifest>  

 

2、Uri介紹

Uri 表明了要操做的數據,Uri 主要包含了兩部分信息:一、須要操做的
ContentProvider;二、對ContentProvider中的什麼數據進行操做。一個Uri由以
下幾部分組成: 
數據庫

ContentProvider的scheme已經由Android所規定,scheme爲content://。 
主機名(authorities)用於惟一標識這個ContentProvider,外部調用者能夠根據
它找到對應的內容提供者(ContentProvider)。 
路徑(Path)能夠用來表示咱們要操做的數據,路徑的構建應該根據業務而定,
以下: 
要操做Person表中ID 爲10的記錄,能夠構建這樣的路徑:/person/id/10,也
能夠爲/prson/10,構建什麼樣的路徑須要與UriMatcher中註冊的匹配Uri相一
致。例如:/person/id/10,那麼匹配Uri須要也須要帶id 爲/preson/id/#,不然
能夠寫成/person/10. 
要操做person表中的全部記錄,能夠這樣構建路徑:/person 
若是要把一個字符串轉換成Uri,可使用Uri類中的parse()方法。以下: 
Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person")   app

3、UriMatcher類使用介紹

由於Uri表明了要操做的數據,因此咱們常常須要解析Uri,並從Uri中獲取數
據。Android提供了兩個用於操做Uri的工具類,分別爲UriMatcher和ContentUris。 
UriMatcher類用於匹配Uri,用法以下: 
一、 首先須要把匹配的Uri路徑所有進行註冊,以下:ide

  1. //常量UriMatcher.NO_MATCH表示不匹配任何路徑的返回碼   
  2. UriMatcher  sMatcher = new UriMatcher(UriMatcher.NO_MATCH);   
  3. //若是match()方法匹配content:  
  4. //com.ljq.provider.personprovider/person路徑,返回匹配碼爲1,匹配Uri註冊以下:   
  5. sMatcher.addURI("com.ljq.provider.personprovider", person", 1);  
  6. //添加須要匹配uri,若是匹配就會返回匹配碼   
  7. //若是match()方法匹配content://com.ljq.provider.personprovider/person/230路徑,返回匹配碼爲2,配Uri註冊以下:   
  8. sMatcher.addURI("com.ljq.provider.personprovider", "person/#", 2);  
  9. //#號爲通配符   
  10. //傳入Uri,進行匹配   
  11. switch (sMatcher.match(Uri.parse("content://com.ljq.provider.personprovider/person/10"))) {    
  12.    case 1   
  13.      break;   
  14.    case 2   
  15.      break;   
  16.    default://不匹配   
  17.      break;   
  18. }   

註冊完須要匹配的Uri後,就可使用sMatcher.match(uri)對輸入的uri進
匹配,若是匹配正確就返回匹配碼,匹配碼是addUri()方法傳入的第三個
數,假設匹配content://com.ljq.provider.personprovider/person 路徑,返回
匹配碼爲1。 工具

 

4、ContentUris介紹

ContentUris用於操做Uri後面的ID 部分,它有兩個實用的方法: 
WithAppendedId(uri, id)用於爲uri路徑加上id 部分,以下: 網站

  1. Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person")   
  2. Uri resultUri = ContentUris.withAppendedId(uri, 10);    
  3. //生成後的Uri爲:content://com.ljq.provider.personprovider/person/10   
  4. parseId(uri)用於從路徑中獲取Id,以下:   
  5. Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person/10")   
  6. long personid = ContentUris.parseId(uri);  
  7. //獲取的結果爲:10   

 

5、使用ContentProvider共享數據

ContentProvider類主要方法的做用: 
一、 public boolean  onCreate():該方法在ContentProvider 建立後就會被調用,
Android開機後,ContentProvider在其它應用第一次訪問它時纔會被建立。 
二、 public  int  insert():該方法用於宮外部應用爲ContentProvider中添加數據使
用。 
三、 public  int  delete(Uri  uri,  String  selection,  String[]  selectionArgs):該方法用於
供外部應用從ContentProvider中刪除數據。 
四、 public  int update(Uri  uri,  ContentValues  values,  String  selection,  String[]
selectionArgs):該方法用於供外部應用更新ContentProvider中的數據。 
五、 public  cursor query(Uri  uri,  String[]  projection,  String  selection,  String[]
selectionArgs, String sortOrder):該方法用於供外部應用查詢ContentProvider
中的數據。 
六、 public String getType(uri):該方法用於返回當前uri表明數據的MIME類型。 
若是操做的數據屬於集合類型,那麼MIME類型字符串應該以
vnd.android.cursor.dir/開頭,例如,要獲得全部person記錄的Uri爲 
content://com.ljq.provider.personprovider/person,那麼返回的MIME類型字
符串應該爲:"vnd.android.cursor.dir/person"。 
若是要操做的數據類型爲非集合類型,那麼MIME類型字符串應該以
vnd.android.cursor.item/開頭。例如:獲得id 爲10的person記錄,Uri爲 
content://com.ljq.provider.personprovider/person/10,那麼返回的MIME類型
字符串爲:"vnd.android.cursor.item/person"。 spa

 

6、使用ContentResovler操做ContentProvider中的數據

當外部應用須要對ContentProvider 中的數據進行操做時,可使用
ContentResovler來完成,可使用Activity的getContentResovler()方法來獲取
CountentResovler對象。ContentResovler提過了和ContentProvider相似的四個
方法: 
public  Uri insert(Uri  uri,  ContentValues  values):該方法用於往ContentProvider
添加數據。 
public int delete(Uri uri, String selection, String[] selectionArgs):該方法用於從
 ContentProvider刪除數據。 
public  int  update(Uri  uri,  ContentValues  values,  String  selection,  String[]
selectionArgs):該方法用於更新ContentProvider中的數據。 
public  Cursor  query(Uri  uri,  String[]  projection,  String  selection,  String[]
selectionArgs, String sortOrder):該方法用於從ContentProvider中獲取數據。 
這些方法的第一個參數爲uri,表明要操做的ContentProvider和對其中的什麼數
據進行操做,假設給定的是: 
Uri.parse("content://com.ljq.providers.personprovider/person/10"),那麼將會對
主機名爲com.ljq.providers.personprovider的ContentProvider進行操做,操做的數
據爲person表中id爲10的記錄。 
使用ContentResovler對ContentProvider中的數據進行增刪改查操做,以下: .net

  1. ContentResolver resolver =  getContentResolver();   
  2. Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person");   
  3. //添加一條記錄   
  4. ContentValues values = new ContentValues();   
  5. values.put("name", "linjiqin");   
  6. values.put("age", 25);   
  7. resolver.insert(uri, values);     
  8. //獲取person表中全部記錄   
  9. Cursor cursor = resolver.query(uri, null, null, null, "personid desc");   
  10. while(cursor.moveToNext()){   
  11.    Log.i("ContentTest", "personid="+ cursor.getInt(0)+ ",name="+ cursor.getString(1));   
  12. }   
  13. //把id爲1的記錄的name字段值更改新爲zhangsan   
  14. ContentValues updateValues = new ContentValues();   
  15. updateValues.put("name", "zhangsan");   
  16. Uri updateIdUri = ContentUris.withAppendedId(uri, 2);   
  17. resolver.update(updateIdUri, updateValues, null, null);  
  18. //刪除id爲2的記錄   
  19. Uri deleteIdUri = ContentUris.withAppendedId(uri, 2);   
  20. resolver.delete(deleteIdUri, null, null);   

 

7、監聽ContentProvider中數據的變化

若是ContentProvider的訪問者須要知道ContentProvider中數據發生變化,能夠
在ContentProvider中數據發生變化時調用getContentResovler().notifyChange(uri, 
null)來通知註冊在此uri上的訪問者,以下: 

  1. public class PersonContentProvider extends ContentProvider {   
  2.    public Uri insert(Uri uri, ContentValues values) {   
  3.       db.insert("person", "personid", values);   
  4.       getContext().getContentResolver().notifyChange(uri, null);   
  5.    }   
  6. }   


若是ContentProvider 的訪問者須要獲得數據變化通知,必須使用
ContentObserver對數據(數據採用Uri描述)進行監聽,當監聽到數據變化通
知時,系統就會調用ContentObserver的onChange()方法,以下: 

  1. getContentResolver().registerContentObserver(Uri.parse("content://com.ljq.providers.personprovider/person"),   
  2.        true, new PersonObserver(new Handler()));   
  3. public class PersonObserver extends ContentObserver{   
  4.    public PersonObserver(Handler handler) {   
  5.       super(handler);   
  6.    }   
  7.    public void onChange(boolean selfChange) {   
  8.       //此處能夠進行相應的業務處理   
  9.    }   
  10. }   

項目地址:

    https://github.com/wangzhiyuan888/ContentProviderDemo

相關文章
相關標籤/搜索