ContentProvider
ContentProvider 在android中的作用是對外共享數據,也就是說你可以通過ContentProvider把應用中的數據共享給其他應用訪問,其他應用可以通過ContentProvider 對你應用中的數據進行添刪改查。
ContentProvider的就是自定義增刪改查接口並暴露出去,讓別的應用訪問自己的數據。ContentResolver就是按照一定規則訪問內容提供者的數據。
ContentProvider對外共享數據步驟:
步驟
1. 定義一個類 繼承 ContentProvider
2. 定義匹配規則 uri
3. 通過靜態代碼塊添加匹配規則
4.在manifest.xml中配置contentProvider.
Uri介紹
uri代表了要操作的數據
上面我們提到了Android提供內容的叫Provider,那么在Android中怎么區分各個Provider?
Uri作為唯一的標識來標識這個Provider。
ContentProvider的scheme為:content://
Authority 用於唯一標識這個ContentProvider,外部調用者可以根據這個標識來找到它。
路徑(path)可以用來表示我們要操作的數據,路徑的構建應根據業務而定,如下:
要操作file表中id為10的記錄,可以構建這樣的路徑:/file/10
要操作file表中id為10的記錄的name字段, file/10/name
要操作file表中的所有記錄,可以構建這樣的路徑:/file
當然要操作的數據可以是數據庫,也可以是文件、xml或網絡等其他存儲方式。
代碼示例
public class FileProvider extends ContentProvider { private Context mContext; private static final int QUEYSUCESS = 0; private static final int INSERTSUCESS = 1; //UriMatcher.NO_MATCH表示不匹配任何路徑的返回碼 private static UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); private SQLiteDatabase mDb; private String mTableName = DbOpenHelper.STUDENT_TABLE_NAME; static{ //注冊所有要匹配的uri mUriMatcher.addURI("com.itcast.contentp.FileProvider", "query", QUEYSUCESS); mUriMatcher.addURI("com.itcast.contentp.FileProvider", "insert", INSERTSUCESS); } //該方法在其它應用第一次訪問它時才會被創建 @Override public boolean onCreate() { mContext = getContext(); mDb = new DbOpenHelper(mContext).getWritableDatabase(); return false; } /** *public final Cursor query (Uri uri, String[] projection,String selection,String[] selectionArgs, String sortOrder) *projection : 這個參數告訴查詢要返回的列(Column)即需要的字段,比如Contacts Provider提供了聯系人的ID和聯系人的NAME等內容. *selection :查詢where字句 *selectionArgs : 查詢條件屬性值 *sortOrder :結果排序 */ @Override public Cursor query(Uri uri, String[] arg1, String arg2, String[] arg3,String arg4) { if (mUriMatcher.match(uri)== QUEYSUCESS ) {//uri匹配后進行下面的操作 Cursor cursor = mDb.query(tableName, arg1, arg2, arg3, null, null, null); getContext().getContentResolver().notifyChange(uri, null); return cursor; }else{ throw new IllegalArgumentException("match fail"); } } 這里只給出部分代碼。。。。。。
ContentResolver
使用ContentResolver調用ContentProvider提供的接口,對ContentProvider中的數據進行添加、刪除、修改和查詢操作時。
可以使用Activity提供的getContentResolver()方法來獲取ContentResolver對象。 ContentResolver 類提供了與ContentProvider類相同簽名的四個方法:
- public Uri insert(Uri uri, ContentValues values)
- public int delete(Uri uri, String selection, String[] selectionArgs)。
- public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
- public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
1.對ContentProvider中的數據進行增刪改查
直接看代碼:
//uriQuery必須與要查詢的ContentProvider中的要操作數據的uri保持一致(btw 這里只給了查詢好插入的例子)
ContentValues values = new ContentValues(); Cursor cursor = getContentResolver().query(uriQuery, null, null, null, null); int count = cursor.getCount(); //獲取到一共有多少行 int contact_id = count + 1; ContentValues nameValues = new ContentValues(); nameValues.put("name", name); nameValues.put("mime_type", "vnd.android.cursor.item/name"); nameValues.put("contact_id", contact_id); getContentResolver().insert(uriInsert, nameValues);
2.監聽ContentProvider中數據的變化
在ContentProvider 發生數據變化時調用getContentResolver().notifyChange(uri, null)來通知注冊在此URI上的訪問者。
當數據放生變化時會調用ContentObserver的onChange()來進行一系列的后續操作~~~
如下:
public class MainActivity extends Activity { private Uri uri; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //注冊 uri = Uri.parse("content://com.example.contentp.AccountProvider");
getContentResolver().registerContentObserver(uri, true, new MyObserver(new Handler()))
}
}
//監聽到變化后調用onChange()來執行一系列操作
private class MyObserver extends ContentObserver { Uri uri = Uri.parse("content://com.example.contentp.AccountProvider");
public MyObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
Cursor cursor = getContentResolver().query(uri, new String[]{"file","mime_type","date"}, null, null, null);
while(cursor.moveToNext()){
//執行一些操作
}
}
}
ContentProviderClient
與ContentResolver一樣都是用來對ContentProvider中的數據進行添加、刪除、修改和查詢操作的
通過調用 getContentResolver().acquireContentProviderClient(authority) 方法獲取 ContentProviderClient對象。
用法跟ContentResolver相似,不同點是ContentProviderClient 對象必須在結束使用后,調用ContentProviderClient.release()來釋放。這會是系統釋放對應的ContentProvider對象。
對於相同ContentProvider 的多次調用,推薦使用ContentProviderClient。
