ContentProvider URI匹配机制详解

ContentProvider 的 URI 匹配机制主要通过 UriMatcher 类实现,用于根据 URI 路径决定如何处理数据请求。以下是其核心机制和用法:


URI 结构

ContentProvider 的 URI 通用格式为:

text 复制代码
content://<authority>/<path>/<id>?<query>
  • authority :ContentProvider 的唯一标识,需与 AndroidManifest.xml 中声明的 android:authorities 一致。
  • path :标识数据表或资源类型(如 users)。
  • id :可选,标识特定记录(如 123)。
  • query:可选参数,不影响 URI 匹配,但用于数据过滤。

UriMatcher 的使用步骤

  1. 定义匹配规则 使用通配符 #(数字)和 *(任意字符)注册 URI 模式:

    java 复制代码
    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 表
    }
  2. 在 ContentProvider 中处理匹配结果 根据 URI 匹配的返回值,执行对应操作:

    java 复制代码
    @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>
java 复制代码
@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() 解析查询参数。

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

java 复制代码
// 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", ...);
}
相关推荐
zFox13 分钟前
四、ViewModel + StateFlow + 状态持久化
kotlin·stateflow·viewmodel
遥不可及zzz1 小时前
Android 接入UMP
android
Coder_Boy_3 小时前
基于SpringAI的在线考试系统设计总案-知识点管理模块详细设计
android·java·javascript
冬奇Lab4 小时前
【Kotlin系列03】控制流与函数:从if表达式到Lambda的进化之路
android·kotlin·编程语言
冬奇Lab4 小时前
稳定性性能系列之十二——Android渲染性能深度优化:SurfaceFlinger与GPU
android·性能优化·debug
冬奇Lab5 小时前
稳定性性能系列之十一——Android内存优化与OOM问题深度解决
android·性能优化
用户74589002079546 小时前
线程池
android
专注前端30年6 小时前
【PHP开发与安全防护实战】性能调优手册
android·安全·php
王正南8 小时前
安卓逆向之LSposed开发(一)
android·xposed·lsposed