提供了统一对外的数据访问接口,能够把本身应用的数据提供出去给的应用程序使用,能够对你的数据进行增删改查,例如 通信录就是其中的一种。java
要想建立一个 Content Provider 须要进行下面几部操做:android
<provider android:name="classpath" android:authorities="com.exmaple.provider.applicationname" />
Public static final Uri CONTENT_URI = Uri.parse("content://com.exmaple.provider.applicationname/elements")
经过 Android 中的 Uri 访问 Content Provider,Uri主要包含下面几部分:content://com.example.earthquake/contentprovider/quakes/1
数据库
咱们通常提供所有查询和指定条数两种支持查询模式:其中一个很是有用的类 UriMatcher,它是一个很是有用的类,能够分析 URI 并肯定它的形势。数据结构
// 建立两个常量来区分不一样的 URI 请求 private static final int ALLROWS = 1; private static final int SINGLE_ROW = 2; private static final UriMatcher uriMatcher; // 填充 UriMatcher 对象,其中 element 结尾的 URI 对应请求全部的数据 // 以 elements/rowid 结尾的 URI 表明请求单行数据 static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI("com.exmaple.message.provider", "elements", ALLROWS); uriMatcher.addURI("com.exmaple.message.provider", "elements/#", SINGLE_ROW); }
在同一个 Content Provider 中,可使用一样的技术来公开其余的 URI,这些 URI 表明了不一样的数据子集或数据库中不一样的表。app
区分了全表和单行查询后,就能够很容易的使用 SQLiteQueryBuilder 类对一个查询应用额外的选择条件,以下面的代码所示:ide
SQLiteQueryBuilder sqb = new SQLiteQueryBuilder(); // 若是是行查询,用传入的行限制结果集 switch (uriMatcher.match(uri)) { case SINGLE_ROW: String rowID = uri.getPathSegments().get(1); sqb.appendWhere(KEY_ID + "=" + rowID); default: break; }
经常使用帮助方法:ui
UriMatcher:用于匹配对应的 Uri 路径
ContentUris:用于操做 Uri 路径后面的 id 部分spa
当应用程序启动时,每一个 Content Provider 的 onCreate 处理程序会再应用程序的主线程中被调用。
和以前的数据库操做同样,最好使用 SQLiteOpenHelper 来延迟打开(必要的地方建立)底层的数据库,直到 Content Provider 的查询或事务方法须要时再打开或建立它。线程
@Override public boolean onCreate() { // 构建一个底层数据库 // 延迟打开数据库,直到须要执行 // 一个查询或者事务时再打开 sqLiteHelper = new MessageSQLiteHelper(getContext(), MessageSQLiteHelper.DATABASE_NAME, null, MessageSQLiteHelper.DATABASE_VERSION); return true; }
要想使用 Content Provider 就必须实现 query 和 getType 方法。Content Provider 使用这些方法来访问底层数据,无需知道底层的数据结构和实现。
Content Provider 的最多见场景就是访问一个 SQLite 数据库,但在这些方法中,你能够访问任何的数据库(包括文件或应用程序实例变量)。
UriMatcher 对象应用于完善事务处理和查询请求,而 SQLiteQueryBuilder 是执行基于行查询的便利辅助类。code
public class StudentContentProvider extends ContentProvider { private SimpleSQLiteHelper sqLiteHelper; // 建立两个常量来区分不一样的 URI 请求 public static final int ALLROWS = 1; public static final int SINGLE_ROW = 2; public static final Uri CONTENT_URI = Uri.parse("content://com.example.contentprovider/students"); private static final UriMatcher uriMatcher; static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI("com.example.contentprovider", "students", ALLROWS); uriMatcher.addURI("com.example.contentprovider", "students/#", SINGLE_ROW); } @Override public boolean onCreate() { sqLiteHelper = new SimpleSQLiteHelper(getContext(), SimpleSQLiteHelper.DATABASE_NAME, null, SimpleSQLiteHelper.DATABASE_VERSION); return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db; try { db = sqLiteHelper.getWritableDatabase(); } catch (SQLiteException e) { db = sqLiteHelper.getReadableDatabase(); } // 设定分组和聚合条件 String groupBy = null; String having = null; SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); switch (uriMatcher.match(uri)) { case SINGLE_ROW: String rowID = uri.getPathSegments().get(1); queryBuilder.appendWhere(SimpleSQLiteHelper.KEY_ID + " = " + rowID); break; default: break; } // 指定要执行查询的表,根据须要,这能够是一个特定的表或者一个链接 queryBuilder.setTables(SimpleSQLiteHelper.DATABASE_TABLE); // 执行查询操做 Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, groupBy, having, sortOrder); return cursor; } @Override public String getType(Uri uri) { // 为一个 Content Provider URI 返回一个字符串,它标识了 MIME 类型 switch (uriMatcher.match(uri)) { case ALLROWS: return "vnd.android.cursor.dir/vnd.example.contentprovider.elemental"; case SINGLE_ROW: return "vnd.android.cursor.item/vnd.example.contentprovider.elemental"; default: throw new IllegalArgumentException("Unsupported URI: " + uri); } } @Override public Uri insert(Uri uri, ContentValues values) { // 打开一个可写的数据库链接 SQLiteDatabase db = sqLiteHelper.getWritableDatabase(); String nullColumnHack = null; // 向表中插入值 long id = db.insert(SimpleSQLiteHelper.DATABASE_TABLE, nullColumnHack, values); if (id > -1) { // 构造并返回插入行的 URI Uri insertedId = ContentUris.withAppendedId(CONTENT_URI, id); // 通知全部的观察者,数据集已经改变 getContext().getContentResolver().notifyChange(insertedId, null); return insertedId; } return null; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // 打开一个可写的数据库链接 SQLiteDatabase db = sqLiteHelper.getWritableDatabase(); // 若是是行 URI,限定删除行为指定的行 switch (uriMatcher.match(uri)) { case SINGLE_ROW: String rowID = uri.getPathSegments().get(1); selection = SimpleSQLiteHelper.KEY_ID + " = " + rowID + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ")" : ""); break; default: break; } // 要想返回删除的项的数量,必须指定一条 where 子句,要删除全部的行并返回一个值,则传入 1 if (selection == null) { selection = "1"; } // 执行删除操做 int deleteCount = db.delete(SimpleSQLiteHelper.DATABASE_TABLE, selection, selectionArgs); // 通知全部的观察者,数据集已经改变 getContext().getContentResolver().notifyChange(uri, null); return deleteCount; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // 打开一个可写的数据库链接 SQLiteDatabase db = sqLiteHelper.getWritableDatabase(); // 若是是行 URI,限定删除行为指定的行 switch (uriMatcher.match(uri)) { case SINGLE_ROW: String rowID = uri.getPathSegments().get(1); selection = SimpleSQLiteHelper.KEY_ID + " = " + rowID + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ")" : ""); break; default: break; } // 执行更新 int updateCount = db.update(SimpleSQLiteHelper.DATABASE_TABLE, values, selection, selectionArgs); // 通知全部的观察者,数据集已经改变 getContext().getContentResolver().notifyChange(uri, null); return updateCount; } }
能够经过 Content Resolver 来访问 Content Provider 提供的数据。能够经过 getContext().getContentResolver()
方法来获取一个 Content Resolver 对象。
若是 共享的数据发生变化,能够在 Content Provider 发生数据变化时调用 getCotentResolver().notifyChange(uri, null)
来通知注册在此 URI 上的访问者