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 的使用步骤

  1. 定义匹配规则
    使用通配符 #(数字)和 *(任意字符)注册 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 表
}
  1. 在 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/abcpath/123)。

匹配优先级

  • 精确路径优先于通配符。例如,若同时注册 users/#users/*,URI users/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> 标签限制访问权限。
  • 参数处理:利用 UrigetQueryParameter() 解析查询参数。

示例场景:处理用户和书籍数据

// 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", ...);
}