Android四大元件--ContentProvider
一、簡介
ContentProvider是Android四大元件之一的內容提供器
ContentProvider為儲存和獲取資料提供了統一的介面,使用表的形式來對資料進行封裝,使得開發者在後續的開發過程中不用關心資料儲存的細節。使用ContentProvider可以在不同的應用程式之間共享資料,Android為常見的資料型別提供了預設的ContentProvider(包括音訊、視訊、圖片和通訊錄等)。
總的來說,利用ContentProvider來實現共享資料的好處是統一了資料的訪問方式。
二、使用方法
ContentProvide的使用涉及ContentProvider、 ContentObserver、 ContentReslover 、ContentValues、Cursor、Uri、UriMatcher以及資料庫等。
ContentProvider,它最大的特點是可以在應用之間共享資料
1.定義自己的ContentProvide類,
2.在AndroidManifest.xml上註冊,並指定authorities屬性,給外界提供固定Uri對外提供服務
- 提供的方法
操作方法:insert、getType、delete、query、update、oncreate用於建立資料庫或連結資料庫,以及提供為contentResolver增刪改查的方法。
ContentValues是用於儲存ContentResolver處理的值。
ContentResolver用於訪問content模型,其實就是訪問和操作contentprovider。
- 實現方式
Context提供了getContentResolver方法,這表明Activity、Service元件都可通過該方法獲取該類的例項
ContentResolver提供的操作方法:
insert、getType、delete、query、update等與ProvideContent相對應,通過Uri連結ContentProvide和ContentResolver
Cursor類,遊標。應用時一般通過查詢query得到。
Uri:協議部分、域名、路徑、ID、欄位
其中協議部分:content://
域名對應authoties屬性
路徑:資源部分或資料部分
三、ContentProvider類主要方法的介紹:
-
public boolean onCreate(),在ContentProvider建立後就會被呼叫,而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中獲取資料;
-
public String getType(Uri uri),返回當前Uri所代表資料的MIME型別;
如果操作的資料屬於集合型別,那麼MIME型別字串應該以vnd.android.cursor.dir/開頭,如要得到所有tablename記錄的Uri為content://com.wang.provider.myprovider/tablename ,那麼返回的MIME型別字串應該為:vnd.android.cursor.dir/table。
如果要操作的資料屬於非集合型別資料,那麼MIME型別字串應該以vnd.android.cursor.item/開頭,如得到id為10的tablename記錄,Uri為content://com.wang.provider.myprovider/tablename/10 ,那麼返回的MIME型別字串為:vnd.android.cursor.item/tablename 。
四、UriMatcher
Uri代表要操作的資料,在開發過程中對資料進行獲取時需要解析Uri,Android提供了兩個用於操作Uri的工具類,分別為UriMatcher和ContentUris 。掌握它們的基本概念和使用方法,對一個Android開發者來說是一項必要的技能。
1、UriMatcher
UriMatcher類用於匹配Uri,它的使用步驟如下:
- a、將需要匹配的Uri路徑進行註冊,程式碼如下:
1 //常量UriMatcher.NO_MATCH表示不匹配任何路徑的返回碼 2 UriMatchersMatcher = new UriMatcher(UriMatcher.NO_MATCH); 3 //如果match()方法匹配“content://com.wang.provider.myprovider/tablename”路徑,返回匹配碼為1 4 sMatcher.addURI("content://com.wang.provider.myprovider", " tablename ", 1); 5//如果match()方法匹配content://com.wang.provider.myprovider/tablename/11路徑,返回匹配碼為2 6 sMatcher.addURI("com.wang.provider.myprovider", "tablename/#", 2);
注意:新增第二個URI時,路徑後面的id採用了萬用字元形式“#”,表示只要前面三個部分都匹配上了就OK。
- b、註冊完需要匹配的Uri後,可以使用sMatcher.match(Uri)方法對輸入的Uri進行匹配,如果匹配就返回對應的匹配碼,匹配碼為呼叫addURI()方法時傳入的第三個引數。
switch (sMatcher.match(Uri.parse("content://com.zhang.provider.yourprovider/tablename/100"))) { case 1: //match 1, todo something break; case 2 //match 2, todo something break; default: //match nothing, todo something break; }
2、ContentUris
ContentUris類用於操作Uri路徑後面的ID部分,它有兩個比較實用的方法:
withAppendedId(Uri uri, long id)和parseId(Uri uri)。
withAppendedId(Uri uri, long id)用於為路徑加上ID部分:
Uri uri = Uri.parse("content://com.wang.provider.myprovider/tablename"); Uri resultUri = ContentUris.withAppendedId(uri, 10);
parseId(Uri uri)則從路徑中獲取ID部分:
Uri uri = Uri.parse("content://com.zhang.provider.myprovider/tablename/10"); long personid = ContentUris.parseId(uri);
五、ContentResolver操作資料
當外部應用需要對ContentProvider中的資料進行新增、刪除、修改及查詢操作時,可以使用ContentResolver 類來完成。而要獲取ContentResolver 物件,可以使用Activity提供的getContentResolver()方法。
ContentResolver 類提供了與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和對其中的什麼資料進行操作,其實和ContentProvider裡面的方法是一樣的。他們所對應的資料,最終會被傳到我們在之前程式裡面定義的那個ContentProvider類的方法,假設給定的是:Uri.parse("content://com.wang.provider.myprovider/tablename/10 "),那麼將會對主機名為com.wang.provider.myprovider 的ContentProvider進行操作,操作的資料為tablename表中id為10的記錄。
使用ContentResolver對ContentProvider中的資料進行操作的程式碼如下:
ContentResolver resolver = getContentResolver(); Uri uri = Uri.parse("content://com.wang.provider.myprovider/tablename"); //新增一條記錄 ContentValues values = new ContentValues(); values.put("name", "wang1"); values.put("age", 28); resolver.insert(uri, values); //獲取tablename表中所有記錄 Cursor cursor = resolver.query(uri, null, null, null, "tablename data"); while(cursor.moveToNext()){ Log.i("ContentTest", "tablename_id="+ cursor.getInt(0)+ ", name="+ cursor.getString(1)); } //把id為1的記錄的name欄位值更改新為zhang1 ContentValues updateValues = new ContentValues(); updateValues.put("name", "zhang1"); Uri updateIdUri = ContentUris.withAppendedId(uri, 2); resolver.update(updateIdUri, updateValues, null, null); //刪除id為2的記錄,即欄位age Uri deleteIdUri = ContentUris.withAppendedId(uri, 2); resolver.delete(deleteIdUri, null, null);
六、監聽資料變化
如果ContentProvider的訪問者需要知道資料發生的變化,可以在ContentProvider發生資料變化時呼叫getContentResolver().notifyChange(uri, null)來通知註冊在此URI上的訪問者。只給出類中監聽部分的程式碼:
public class MyProvider extends ContentProvider { public Uri insert(Uri uri, ContentValues values) { db.insert("tablename", "tablenameid", values); getContext().getContentResolver().notifyChange(uri, null); } }
而訪問者必須使用ContentObserver對資料(資料採用uri描述)進行監聽,當監聽到資料變化通知時,系統就會呼叫ContentObserver的onChange()方法:
getContentResolver().registerContentObserver(Uri.parse("content://com.ljq.providers.personprovider/person"), true, new PersonObserver(new Handler())); public class PersonObserver extends ContentObserver{ public PersonObserver(Handler handler) { super(handler); } public void onChange(boolean selfChange) { //to do something } }
參考學習:https://www.cnblogs.com/tgyf/p/4696288.html
寫在最後: 本系列的文章旨在學習過程中的總結,如果對你也有幫助,榮幸之至。