1.什么是ContentProvider?
ContentProvider是安卓的四大组件之一,主要的作用就是和第三方应用共享数据,其他应用也可以通过ContentProvider对指定应用中的数据进行操作。ContentProvider分为系统的和自定义的,系统的如联系人和图片等数据。
Google Doc中对ContentProvider的大致概述:
内容提供者将一些特定的应用程序数据供给其它应用程序使用。内容提供者继承于ContentProvider
基类,为其它应用程序取用和存储它管理的数据实现了一套标准方法。然而,应用程序并不直接调用这些方法,而是使用一个 ContentResolver 对象,调用它的方法作为替代。ContentResolver可以与任意内容提供者进行会话,与其合作来对所有相关交互通讯进行管理。
2.ContentProvider的创建?
public class MyContentProvider extends ContentProvider{
@Override
public boolean onCreate() {//在创建ContentProvider时调用
return false;
}
@Nullable
@Override
public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {//用于查询指定Uri的ContentProvider,返回一个Cursor
return null;
}
@Nullable
@Override
public String getType(Uri uri) {//用于返回指定的Uri中的数据的MIME类型
return null;
}
@Nullable
@Override
public Uri insert(Uri uri, ContentValues contentValues) {//用于添加数据到指定Uri的ContentProvider中
return null;
}
@Override
public int delete(Uri uri, String s, String[] strings) {//用于从指定Uri的ContentProvider中删除数据
return 0;
}
@Override
public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {//用于更新指定Uri的ContentProvider中的数据
return 0;
}
}
3.实例代码
先来设计一个数据库,用来存储笔记信息,主要包含_ID,title,content,create_date四个字段。创建NoteProviderMetaData类,封装URI和数据库、表、字段相关信息,源码如下:
public class NoteProviderMetaData {
public static final String AUTHORITY = "com.keyi.mycontentprovider.NoteProvider";
public static final String DATABASE_NAME = "note.db";
public static final int DATABASE_VERSION = 1;
/**
* *
* *数据库中表相关的元数据
*
*/
public static final class NoteTableMetaData implements BaseColumns {
public static final String TABLE_NAME = "notes";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/notes");
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.alexzhou.note";
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.alexzhou.note";
public static final String NOTE_TITLE = "title";
public static final String NOTE_CONTENT = "content";
public static final String CREATE_DATE = "create_date";
public static final String DEFAULT_ORDERBY = "create_date DESC";
public static final String SQL_CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "(" + _ID + " INTEGER PRIMARY KEY,"
+ NOTE_TITLE + " VARCHAR(50),"
+ NOTE_CONTENT + " TEXT,"
+ CREATE_DATE + " INTEGER"
+ ");";
}
}
内容提供者和数据库public class MyContentProvider extends ContentProvider {
private static final UriMatcher sUriMatcher;
private static final int COLLECTION_INDICATOR = 1;
private static final int SINGLE_INDICATOR = 2;
private DatabaseHelper mDbHelper;
static {
sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
sUriMatcher.addURI(NoteProviderMetaData.AUTHORITY, "notes", COLLECTION_INDICATOR);
sUriMatcher.addURI(NoteProviderMetaData.AUTHORITY, "notes/#", SINGLE_INDICATOR);
}
private static HashMap<String, String> sNotesProjectionMap;
static {
sNotesProjectionMap = new HashMap<String, String>();
sNotesProjectionMap.put(NoteProviderMetaData.NoteTableMetaData._ID, NoteProviderMetaData.NoteTableMetaData._ID);
sNotesProjectionMap.put(NoteProviderMetaData.NoteTableMetaData.NOTE_CONTENT, NoteProviderMetaData.NoteTableMetaData.NOTE_CONTENT);
sNotesProjectionMap.put(NoteProviderMetaData.NoteTableMetaData.NOTE_TITLE, NoteProviderMetaData.NoteTableMetaData.NOTE_TITLE);
sNotesProjectionMap.put(NoteProviderMetaData.NoteTableMetaData.CREATE_DATE, NoteProviderMetaData.NoteTableMetaData.CREATE_DATE);
}
@Override
public boolean onCreate() {//在创建ContentProvider时调用
mDbHelper = new DatabaseHelper(this.getContext());
return true;
}
//实现query方法,这里借助SQLiteQueryBuilder来为查询设置投影映射以及设置相关查询条件,
// 返回的是一个Cursor对象,它是一个行集合,包含0和多个记录,类似于JDBC中的ResultSet,可以前后移动游标,
// 得到每行每列中的数据。注意的是,使用它需要调用moveToFirst(),因为游标默认是在第一行之前。
@Nullable
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {//用于查询指定Uri的ContentProvider,返回一个Cursor
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
switch (sUriMatcher.match(uri)) {
case COLLECTION_INDICATOR:
// 设置查询的表
queryBuilder.setTables(NoteProviderMetaData.NoteTableMetaData.TABLE_NAME);
// 设置投影映射
queryBuilder.setProjectionMap(sNotesProjectionMap);
break;
case SINGLE_INDICATOR:
queryBuilder.setTables(NoteProviderMetaData.NoteTableMetaData.TABLE_NAME);
queryBuilder.setProjectionMap(sNotesProjectionMap);
queryBuilder.appendWhere(NoteProviderMetaData.NoteTableMetaData._ID + "=" + uri.getPathSegments().get(1));
break;
default:
throw new IllegalArgumentException("Unknow URI: " + uri);
}
String orderBy;
if (TextUtils.isEmpty(sortOrder)) {
orderBy = NoteProviderMetaData.NoteTableMetaData.DEFAULT_ORDERBY;
} else {
orderBy = sortOrder;
}
SQLiteDatabase db = mDbHelper.getReadableDatabase();
Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, orderBy);
return cursor;
}
@Nullable
@Override
public String getType(Uri uri) {//用于返回指定的Uri中的数据的MIME类型
switch(sUriMatcher.match(uri)) {
case COLLECTION_INDICATOR:
return NoteProviderMetaData.NoteTableMetaData.CONTENT_TYPE;
case SINGLE_INDICATOR:
return NoteProviderMetaData.NoteTableMetaData.CONTENT_ITEM_TYPE;
default:
throw new IllegalArgumentException("Unknow URI: " + uri);
}
}
//实现insert方法,实现把记录插入到基础数据库中,然后返回新创建的记录的URI
@Nullable
@Override
public Uri insert(Uri uri, ContentValues values) {//用于添加数据到指定Uri的ContentProvider中
if (sUriMatcher.match(uri) != COLLECTION_INDICATOR) {
throw new IllegalArgumentException("Unknown URI " + uri);
}
SQLiteDatabase db = mDbHelper.getWritableDatabase();
long rowID = db.insert(NoteProviderMetaData.NoteTableMetaData.TABLE_NAME, null, values);
if (rowID > 0) {
Uri retUri = ContentUris.withAppendedId(NoteProviderMetaData.NoteTableMetaData.CONTENT_URI, rowID);
return retUri;
}
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {//用于从指定Uri的ContentProvider中删除数据
SQLiteDatabase db = mDbHelper.getWritableDatabase();
int count = -1;
switch(sUriMatcher.match(uri)) {
case COLLECTION_INDICATOR:
count = db.delete(NoteProviderMetaData.NoteTableMetaData.TABLE_NAME, selection, selectionArgs);
break;
case SINGLE_INDICATOR:
String rowID = uri.getPathSegments().get(1);
count = db.delete(NoteProviderMetaData.NoteTableMetaData.TABLE_NAME, NoteProviderMetaData.NoteTableMetaData._ID + "=" + rowID, null);
break;
default:
throw new IllegalArgumentException("Unknow URI :" + uri);
}
// 更新数据时,通知其他ContentObserver
this.getContext().getContentResolver().notifyChange(uri, null);
return count;
}
//实现update方法,根据传入的列值和where字句来更新记录,返回更新的记录数,
@Override
public int update(Uri uri, ContentValues values, String s, String[] strings) {//用于更新指定Uri的ContentProvider中的数据
SQLiteDatabase db = mDbHelper.getWritableDatabase();
int count = -1;
switch (sUriMatcher.match(uri)) {
case COLLECTION_INDICATOR:
count = db.update(NoteProviderMetaData.NoteTableMetaData.TABLE_NAME, values, null, null);
break;
case SINGLE_INDICATOR:
String rowID = uri.getPathSegments().get(1);
count = db.update(NoteProviderMetaData.NoteTableMetaData.TABLE_NAME, values, NoteProviderMetaData.NoteTableMetaData._ID + "=" + rowID, null);
break;
default:
throw new IllegalArgumentException("Unknow URI : " + uri);
}
this.getContext().getContentResolver().notifyChange(uri, null);//notifyChange函数是在更新数据时,通知其他监听对象。
return count;
}
private static class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
super(context, NoteProviderMetaData.DATABASE_NAME, null, NoteProviderMetaData.DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.e("DatabaseHelper", "create table: " + NoteProviderMetaData.NoteTableMetaData.SQL_CREATE_TABLE);
db.execSQL(NoteProviderMetaData.NoteTableMetaData.SQL_CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + NoteProviderMetaData.NoteTableMetaData.TABLE_NAME);
onCreate(db);
}
}
}
最后是测试代码:
public class MainActivity extends Activity {
public static final String AUTHORITY = "com.keyi.mycontentprovider.NoteProvider";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/notes");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
insert();
query();
}
private void insert() {
ContentValues values = new ContentValues();
values.put("title", "hello");
values.put("content", "my name is alex zhou");
long time = System.currentTimeMillis();
values.put("create_date", time);
Uri uri = this.getContentResolver().insert(CONTENT_URI, values);
Log.e("test ", uri.toString());
}
private void query() {
Cursor cursor = this.getContentResolver().query(CONTENT_URI, null, null, null, null);
Log.e("test ", "count=" + cursor.getCount());
cursor.moveToFirst();
while(!cursor.isAfterLast()) {
String title = cursor.getString(cursor.getColumnIndex("title"));
String content = cursor.getString(cursor.getColumnIndex("content"));
long createDate = cursor.getLong(cursor.getColumnIndex("create_date"));
Log.e("test ", "title: " + title);
Log.e("test ", "content: " + content);
Log.e("test ", "date: " + createDate);
cursor.moveToNext();
}
cursor.close();
}
}
需要在AndroidManifest.xml中注册:
<provider android:name=".MyContentProvider" android:authorities="com.keyi.mycontentprovider.NoteProvider"/>