1. 程式人生 > >Android四大元件之使用ContentProvider實現資料共享

Android四大元件之使用ContentProvider實現資料共享

ContendProvider是不同應用程式之間進行資料交換的標準API,ContentProvider以某種Uri的形式對外提供資料,允許其他應用訪問或修改資料;其他應用程式使用ContentReslover根據Uri去訪問操作指定資料

因為ContendProvider是四大元件之一,所以也需要在清單檔案配置:

<!--下面配置中name屬性指定ContentProvider類,
authorities就相當於為該ContentProvider指定域名
exported指定該ContentProvider是否允許其他程式呼叫-->
<provider android:name
=".*****" android:authorities="*****" android:exported="true"/>

Uri簡介:Uri就是應用之間通過CotentProvider訪問資料的一個標識
,應用之間標識一致才能訪問
它分為如下三個部分:
1.content:// 這個部分是協議預設的,必須打頭寫的
2.這個部分就是ContentProvider的authorities,就是由這個部分來找到操作那個ContentProvider的,只要訪問指定的ContentProvider這個部分就是固定的
3.words:資源部分(或者說資料部分)當訪問者需要訪問不同資源時,這個部分就是動態改變的

ContentProvider的作用:是暴露可供操作的資料;其他應用程式則通過ContentResolver來操作ContentProvider暴露的資料。
Context提供getContentResolver來獲取ContentResolver物件

開發ContentProvider子類

public class FirstProvider extends ContentProvider
{
   //第一次建立該ContentProvider時呼叫該方法
   @Override
   public boolean onCreate()
   {
       System.out.println("===onCreat方法被呼叫===="
); return true; } //該方法的返回值代表了該ContentProvider所提供資料的MIME型別 @Override public String getType(Uri uri) { return null; } //實現查詢方法,該方法應該返回查詢得到的Cursor @Override public Cursor qurey(Uri uri,String[] projection,String where, String[] whereArgs,String sortOrder) { System.out.println(uri+"===query方法被呼叫===="); System.out.println("where引數為:"+where); return null; } //實現插入的方法,該方法應該返回新插入的記錄的Uri @Override public Uri insert(Uri uri,ContentValues values) { System.out.println(uri+"===insert方法被呼叫===="); System.out.println("values引數為:"+values); return null; } //實現更新方法,該方法應該返回被更新的記錄條數 @Override public int update(Uri uri,ContentProvider values,String where,String[] whereArgs) { System.out.println(uri+"===update方法被呼叫===="); System.out.println("where引數為:"+where+",values引數為:"+values); return 0; } //實現刪除方法,該方法返回被刪除的記錄條數 @Override public int delete(Uri uri,String where ,String[] whereArgs) { System.out.println(uri+"===delete方法被呼叫===="); System.out.println("where引數為:"+where); return 0; } }

建立ContentProvider說明
1.關於生命週期
ContentProvider只有一個onCreate()生命週期方法,當其他應用通過ContentResolver第一次訪問ContentProvider時,onCreate()將會被呼叫,且只會被呼叫一次;ContentProvider提供的query(),insert(),update(),delete()方法則由其他應用通過ContentResolver呼叫

URiMatcher:為了確定該ContentProvider實際能處理的Uri,以及確定每個方法中Uri引數所操作的資料所產生的工具類
主要有兩個方法:
1.void addURI(String authority,String path,int code):該方法用於向UriMatcher物件註冊Uri,其中authority和path組合成一個Uri,而code則代表該Uri對應的標識碼。
2.int mathc(Uri uri):根據前面註冊的Uri來判斷指定Uri對應的標識碼。如果找不到匹配的標識碼,該方法將會返回-1.

/** 一個標識碼對應的是1,一個對應的是2
 *  至於到底需要為UriMatcher物件註冊多少個Uri,則取決於系統的業務需
 *  求。
 */
UriMatcher matcher=new Urimatcher(UriMatcher.NO_MATCH);
//
matcher.addURI("*****","words",1);
matcher.addURI("*****","word/#",2);
//返回標識碼1
matcher.match(Uri.parse("content://*****/words"));
//返回標識碼2
matcher.match(Uri.parse("content://*****/word/2"));
//返回標識碼2
matcher.match(Uri.parse("content://*****/word/10"));

ContentUris:它是一個操作Uri字串的工具類,提供瞭如下兩個工具方法:
1.withAppendedId(uri,id):用於為路徑加上ID部分,例如:

Uri uri=Uri.parse("content://com.example.teacher/word")
Uri resultUri=ContentUris.withAppendId(uri,2);
//生成後的Uri為"content://com.example.teacher/word/2"

2.parseId(uri):用於從指定Uri解析出所包含的ID值。例如:

Uri uri=Uri.parse("content://com.example.teacher/word/2");
long wordId=ContentUris.parseId(uri);//獲取的結果為2

ContentValues 和HashTable類似都是一種儲存的機制 但是兩者最大的區別就在於,contenvalues只能儲存基本型別的資料,像string,int之類的,不能儲存物件這種東西,而HashTable卻可以儲存物件。

在忘資料庫中插入資料的時候,首先應該有一個ContentValues的物件所以:

ContentValues initialValues = new ContentValues();

initialValues.put(key,values);

SQLiteDataBase sdb ;

sdb.insert(database_name,null,initialValues);

插入成功就返回記錄的id否則返回-1;

Android本身就提供了大量的ContentProvider,下面是常用的Uri:

1.ContactsContract.Contacts.CONTENT_URI:管理聯絡人的Uri.
2.ContactsContract.CommonDataKinds.Phone.CONTENT_URI:管理聯絡人的電話的Uri.
3.ContactsContract.CommonDataKinds.Email.CONTENT_URI:管理聯絡人的E-mail的Uri.
4,MediaStroe.Audio.Media.EXTERNAL_CONTENT_URI:儲存在外部儲存器上的音訊檔案內容的ContentProvider的Uri;
5.MediaStroe.Audio.Media.INTERNAL_CONTENT_URI:儲存在手機內部儲存器上的音訊檔案內容的ContentProvider的Uri.
6.MediaStore.Images.Media.EXTERNAL_CONTENT_URI:儲存在外部儲存器上的圖片檔案內容的ContentProvider的Uri.
7.MediaStore.Images.Media.INTERNAL_CONTENT_URI:儲存在手機內部儲存器上的圖片檔案內容的ContentProvider的Uri.
8.MediaStore.Video.Media.EXTERNAL_CONTENT_URI:儲存在外部儲存器上的圖片檔案內容的ContentProvider的Uri.
9.MediaStore.Images.Media.INTERNAL_CONTENT_URI:儲存在手機內部儲存器上的圖片檔案內容的ContentProvider的Uri.

ContentObserver:用於監聽ContentProvider所共享的資料的改變提供響應。
其實只要導致ContentProvider資料的改變就回呼叫如下程式碼:

getContext().getContentResolver().notifyChange(uri,null);

為了在應用程式監聽ContentProvider資料的改變,需要利用Android提供的ContentObserver基類,繼承它並重寫onChange(boolean selfChange)方法,當它所監聽的ContentProvider資料發生改變時,就會觸發onChange(boolean selfChange)方法。

為了監聽指定ContentProvider的資料變化,需要通過ContentProvider向指定Uri註冊ContentObserver監聽器。ContentResolver提供瞭如下方法來註冊監聽器:
registerContentObserver(Uri uri,boolean notifyForDescendents,ContentObserver observer)
uri:該監聽器所監聽的ContentProvider的Uri,
notifyForDescendents:如果該引數設為true,假如註冊監聽的Uri為content://abc,那麼Uri為content://abc/xyz、content://abc/xyz/zoo的資料改變時也會觸發該監聽器。如果該引數設為不false,假如註冊監聽的Uri為content://abc,那麼只有content://abc的資料發生改變時才會觸發該監聽器。
observer:監聽器例項

掌握以上只是基本就掌握了,只是還是需要實際動手操作一番。