ContentProvider URI匹配机制详解
ContentProvider 的 URI 匹配机制主要通过 UriMatcher 类实现,用于根据 URI 路径决定如何处理数据请求。以下是其核心机制和用法:
URI 结构
ContentProvider 的 URI 通用格式为:
content://<authority>/<path>/<id>?<query>
- authority:ContentProvider 的唯一标识,需与
AndroidManifest.xml中声明的android:authorities一致。 - path:标识数据表或资源类型(如
users)。 - id:可选,标识特定记录(如
123)。 - query:可选参数,不影响 URI 匹配,但用于数据过滤。
UriMatcher 的使用步骤
-
定义匹配规则
使用通配符#(数字)和*(任意字符)注册 URI 模式:private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); // 匹配常量 private static final int CODE_USERS = 1; private static final int CODE_USER_ID = 2; private static final int CODE_PRODUCTS = 3; static { sUriMatcher.addURI("com.example.provider", "users", CODE_USERS); // 匹配 users 表 sUriMatcher.addURI("com.example.provider", "users/#", CODE_USER_ID); // 匹配特定用户 sUriMatcher.addURI("com.example.provider", "products", CODE_PRODUCTS); // 匹配 products 表 } -
在 ContentProvider 中处理匹配结果
根据 URI 匹配的返回值,执行对应操作:@Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { switch (sUriMatcher.match(uri)) { case CODE_USERS: // 查询所有用户 return queryAllUsers(); case CODE_USER_ID: // 提取 ID 并查询单条记录 String id = uri.getLastPathSegment(); return queryUserById(id); case CODE_PRODUCTS: // 查询所有商品 return queryAllProducts(); default: throw new IllegalArgumentException("Unknown URI: " + uri); } }
通配符规则
#:匹配数字(如users/123)。*:匹配任意字符(如path/*可匹配path/abc或path/123)。
匹配优先级
- 精确路径优先于通配符。例如,若同时注册
users/#和users/*,URIusers/123会优先匹配users/#。 - 若无匹配项,
UriMatcher.match()返回UriMatcher.NO_MATCH,需处理异常。
MIME 类型关联
根据 URI 返回对应的 MIME 类型:
- 多条数据:
vnd.android.cursor.dir/vnd.<authority>.<path> - 单条数据:
vnd.android.cursor.item/vnd.<authority>.<path>
@Override
public String getType(Uri uri) {
switch (sUriMatcher.match(uri)) {
case CODE_USERS:
return "vnd.android.cursor.dir/vnd.com.example.provider.users";
case CODE_USER_ID:
return "vnd.android.cursor.item/vnd.com.example.provider.users";
default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
}
常见操作示例
- 插入数据:通常使用基础 URI(如
content://com.example.provider/users),返回新记录的 URI(如content://com.example.provider/users/456)。 - 批量更新/删除:通过 URI 是否包含 ID 区分操作范围(更新所有记录或特定记录)。
最佳实践
- URI 定义为常量:避免硬编码,便于维护和跨应用访问。
- 权限控制:通过
AndroidManifest.xml的<permission>标签限制访问权限。 - 参数处理:利用
Uri的getQueryParameter()解析查询参数。
示例场景:处理用户和书籍数据
// UriMatcher 注册
sUriMatcher.addURI("com.example.library", "users", CODE_USERS);
sUriMatcher.addURI("com.example.library", "users/#", CODE_USER_ID);
sUriMatcher.addURI("com.example.library", "books", CODE_BOOKS);
// 在 query() 中
switch (sUriMatcher.match(uri)) {
case CODE_USERS:
return db.query("users", ...);
case CODE_USER_ID:
String userId = uri.getLastPathSegment();
return db.query("users", "id=?", new String[]{userId}, ...);
case CODE_BOOKS:
return db.query("books", ...);
}

浙公网安备 33010602011771号