標籤:地址 path java com 插入 des 表示 segment ret
一、ContentProvider的概念
ContentProvider:為儲存和擷取資料提供統一的介面。可以在不同的應用程式之間共用資料。Android已經為常見的一些資料提供了預設的ContentProvider
1、ContentProvider使用表的形式來組織資料
無論資料的來源是什麼,ContentProvider都會認為是一種表,然後把資料群組織成表格
2、ContentProvider提供的方法
query:查詢
insert:插入
update:更新
delete:刪除
getType:得到資料類型
onCreate:建立資料時調用的回呼函數
3、每個ContentProvider都有一個公用的URI,這個URI用於表示這個ContentProvider所提供的資料。Android所提供的ContentProvider都存放在android.provider包當中
二、ContentProvider的內部原理
自訂一個ContentProvider,來實現內部原理
步驟:
1、定義一個CONTENT_URI常量(裡面的字串必須是唯一)
Public static final Uri CONTENT_URI = Uri.parse("content://com.WangWeiDa.MyContentprovider");
如果有子表,URI為:
Public static final Uri CONTENT_URI = Uri.parse("content://com.WangWeiDa.MyContentProvider/users");
2、定義一個類,繼承ContentProvider
Public class MyContentProvider extends ContentProvider
3、實現ContentProvider的所有方法(query、insert、update、delete、getType、onCreate)
package com.WangWeiDa.cp;
import java.util.HashMap;
import com.WangWeiDa.cp.MyContentProviderMetaData.UserTableMetaData;
import com.WangWeiDa.data.DatabaseHelp;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
public class MyContentProvider extends ContentProvider {
//訪問表的所有列
public static final int INCOMING_USER_COLLECTION = 1;
//訪問單獨的列
public static final int INCOMING_USER_SINGLE = 2;
//操作URI的類
public static final UriMatcher uriMatcher;
//為UriMatcher添加自訂的URI
static{
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(MyContentProviderMetaData.AUTHORITIES,"/user",
INCOMING_USER_COLLECTION);
uriMatcher.addURI(MyContentProviderMetaData.AUTHORITIES,"/user/#",
INCOMING_USER_SINGLE);
}
private DatabaseHelp dh;
//為資料庫表欄位起別名
public static HashMap userProjectionMap;
static
{
userProjectionMap = new HashMap();
userProjectionMap.put(UserTableMetaData._ID,UserTableMetaData._ID);
userProjectionMap.put(UserTableMetaData.USER_NAME, UserTableMetaData.USER_NAME);
}
/**
* 刪除表資料
*/
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
System.out.println("delete");
//得到一個可寫的資料庫
SQLiteDatabase db = dh.getWritableDatabase();
//執行刪除,得到刪除的行數
int count = db.delete(UserTableMetaData.TABLE_NAME, selection, selectionArgs);
return count;
}
/**
* 資料庫訪問類型
*/
@Override
public String getType(Uri uri) {
System.out.println("getType");
//根據使用者請求,得到資料類型
switch (uriMatcher.match(uri)) {
case INCOMING_USER_COLLECTION:
return MyContentProviderMetaData.UserTableMetaData.CONTENT_TYPE;
case INCOMING_USER_SINGLE:
return MyContentProviderMetaData.UserTableMetaData.CONTENT_TYPE_ITEM;
default:
throw new IllegalArgumentException("UnKnown URI"+uri);
}
}
/**
* 插入資料
*/
@Override
public Uri insert(Uri uri, ContentValues values) {
//得到一個可寫的資料庫
SQLiteDatabase db = dh.getWritableDatabase();
//向指定的表插入資料,得到返回的Id
long rowId = db.insert(UserTableMetaData.TABLE_NAME, null, values);
if(rowId > 0){//判斷插入是否執行成功
//如果添加成功,利用新添加的Id和
Uri insertedUserUri = ContentUris.withAppendedId(UserTableMetaData.CONTENT_URI, rowId);
//通知監聽器,資料已經改變
getContext().getContentResolver().notifyChange(insertedUserUri, null);
return insertedUserUri;
}
return uri;
}
/**
* 建立ContentProvider時調用的回呼函數
*/
@Override
public boolean onCreate() {
System.out.println("onCreate");
//得到資料庫協助類
dh = new DatabaseHelp(getContext(),MyContentProviderMetaData.DATABASE_NAME);
return false;
}
/**
* 查詢資料庫
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
//建立一個執行查詢的Sqlite
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
//判斷使用者請求,查詢所有還是單個
switch(uriMatcher.match(uri)){
case INCOMING_USER_COLLECTION:
//設定要查詢的表名
qb.setTables(UserTableMetaData.TABLE_NAME);
//設定表欄位的別名
qb.setProjectionMap(userProjectionMap);
break;
case INCOMING_USER_SINGLE:
qb.setTables(UserTableMetaData.TABLE_NAME);
qb.setProjectionMap(userProjectionMap);
//追加條件,getPathSegments()得到使用者請求的Uri地址截取的數組,get(1)得到去掉地址中/以後的第二個元素
qb.appendWhere(UserTableMetaData._ID + "=" + uri.getPathSegments().get(1));
break;
}
//設定排序
String orderBy;
if(TextUtils.isEmpty(sortOrder)){
orderBy = UserTableMetaData.DEFAULT_SORT_ORDER;
}
else{
orderBy = sortOrder;
}
//得到一個可讀的資料庫
SQLiteDatabase db = dh.getReadableDatabase();
//執行查詢,把輸入傳入
Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);
//設定監聽
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
/**
* 更新資料庫
*/
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
System.out.println("update");
//得到一個可寫的資料庫
SQLiteDatabase db = dh.getWritableDatabase();
//執行更新語句,得到更新的條數
int count = db.update(UserTableMetaData.TABLE_NAME, values, selection, selectionArgs);
return count;
}
}
4、在AndroidMinifest.xml中進行聲明
android:name=".cp.MyContentProvider"
android:authorities="com.WangWeiDa.cp.MyContentProvider"
/>
**為ContentProvider提供一個常量類MyContentProviderMetaData.java
package com.WangWeiDa.cp;
import android.net.Uri;
import android.provider.BaseColumns;
public class MyContentProviderMetaData {
//URI的指定,此處的字串必須和聲明的authorities一致
public static final String AUTHORITIES = "com.wangweida.cp.MyContentProvider";
//資料庫名稱
public static final String DATABASE_NAME = "myContentProvider.db";
//資料庫的版本
public static final int DATABASE_VERSION = 1;
//表名
public static final String USERS_TABLE_NAME = "user";
public static final class UserTableMetaData implements BaseColumns{
//表名
public static final String TABLE_NAME = "user";
//訪問該ContentProvider的URI
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITIES + "/user");
//該ContentProvider所返回的資料類型的定義
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.myprovider.user";
public static final String CONTENT_TYPE_ITEM = "vnd.android.cursor.item/vnd.myprovider.user";
//列名
public static final String USER_NAME = "name";
//預設的排序方法
public static final String DEFAULT_SORT_ORDER = "_id desc";
}
}
Android ContentProvider的介紹