Content Provider 解析URI的方法 UriMatcher的用法和自带的解析方法

原文:https://blog.csdn.net/herbert5069/article/details/7212675 

Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher和ContentUris.

UriMatcher 类的概要描述
这是一个在 content provider 中帮助匹配 URIs 的实用类。

ContentProvider是Android四大组件之一,网上也有不少关于它的文章,基本用法都可以查到,但关于UriMatcher在其中的作用,文章中都有例子,但我觉得还没有说清楚。

先了解一下: Uri

通用资源标志符(Universal Resource Identifier, 简称"URI");

Uri代表要操作的数据,Android上可用的每种资源-图像、视频片段等都可以用Uri来表示。

URI一般由三部分组成:

  1. 访问资源的命名机制。
  2. 存放资源的主机名。
  3. 资源自身的名称,由路径表示。

Android的Uri由以下三部分组成:"content://"、数据路径、标示ID

举例子,如:

  • 所有国家的Uri: content://contacts/country/4
  • 某个国家的Uri:content://contacts/country
  • 某个视频Uri:content://media/video/2

先说为什么用UriMatcher。

实现query、insert.....方法都已经指定操作入口了,为何还要matcher uri,原来是解决多表等情况。

public void addURI (String authority, String path, int code)

这个方法是用来表示在 content provider 里面添加外部对其的匹配的规则,当 URI 被匹配的时候,就会返回 code 码, URI 节点可以精确的匹配字符串, "*" 号匹配任何的字符串 "#" 号只能匹配数字。[比如删除一条记录中 ID 往往是数字]

参数说明

authority : 授权, 就是 AndroidMainifest.xml 中的授权

path : 匹配路径(通常是一个表名)[* 可以作为匹配任意字符的通配符, # 可以作为匹配数字的通配符]。

【注意这里如果是单条记录,需要添加 /# 标示符】
 

UriMatcher使用方法:

  • 第一步,初始化(在contentprovider中的oncreate方法):

--常量 UriMatcher.NO_MATCH 表示不匹配任何路径的返回码(-1)

//URI解析
//1.UriMatcher:在ContentProvider创建时,制定好规则
//当ContentResolver调用ContentProvider的操作方法(会传进来一个uri)
//在相应的操作ContentProvider利用匹配类去匹配uri,根据不同的uri给出不同的处理
UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
  • 第二步注册需要的Uri:(一般在contentprovider中的oncreate方法中制定匹配规则)
matcher.addURI("country", "america", 0);
matcher.addURI("country", "china", 1);
  • 第三步与已经注册的Uri进行匹配(在content):
//假设传入的Uri是这个(可以在contentResolver调用方法传入)
// content://country/america
Uri uri = Uri.parse("content://" + "country" + "/america");
 

//根据上面已经制定的规则,通过match方法进行匹配,
int match = matcher.match(uri);
switch(match) {
         case 0:
         return "logout arimerca";
         case 1:
         return "logout china";
         default:
         return null;
}
 
}

结果返回:logout arimerca

match方法匹配后会返回一个匹配码Code, 即在使用注册方法addURI时传入的第三个参数。


--常量 UriMatcher.NO_MATCH 表示不匹配任何路径的返回码

--#表示通配符

--* 表示任意字符

官方的sdk应该进行修改为

private static final UriMatcher sURIMatcher = new UriMatcher();  
    static  
    {  
        sURIMatcher.addURI("contacts", "people", PEOPLE);  
        sURIMatcher.addURI("contacts", "people/#", PEOPLE_ID);  
        sURIMatcher.addURI("call_log", "calls/filter/*", CALLS_FILTER);  
        sURIMatcher.addURI("call_log", "calls/#", CALLS_ID);  
    }  

第二部分:

ContentProvider向外界提供了一个标准的,也是唯一的用于查询的接口:

public final Cursor query(Uri uri, String[] projection,
            String selection, String[] selectionArgs, String sortOrder);

其中uri用于指定哪一个数据源,当一个数据源含有多个内容(比如多个表),就需要用不同的Uri进行区分,例如:

public static final Uri CONTENT_URI_A = Uri.parse("content://" + AUTHORITY  + "/" + TABLE_A);
public static final Uri CONTENT_URI_B = Uri.parse("content://" + AUTHORITY  + "/" + TABLE_B);

这时候使用UriMatcher就可以帮助我们方便的过滤到TableA还是TableB, 然后进行下一步查询, 如果不用UriMatcher也可以,我们就需要手动过滤字符串,用起来有点麻烦,可维护性也不好。
再说怎么用UriMatcher, 定义如下:

   // Set up our URL matchers to help us determine what an
   // incoming URI parameter is.
   private static final UriMatcher URI_MATCHER;
   static {
      URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
      URI_MATCHER.addURI(AUTHORITY, TABLE_A, TABLE_A_MSG);
      URI_MATCHER.addURI(AUTHORITY, TABLE_B, TABLE_B_MSG);
      
   }

在查询中使用UriMatcher:

 @Override
   public Cursor query(Uri uri, String[] projection, String selection,
         String[] selectionArgs, String sortOrder) {     
 
      String table = null;
 
      switch (URI_MATCHER.match(uri)) {
      case TABLE_A_MSG:
         table = TABLE_A;
         break;
      case TABLE_B_MSG:
         table = TABLE_B;
         break;
      default:
         break;
      }
 
      Cursor resultCursor = mDB.query(table, projection, selection, selectionArgs, null, null, sortOrder);
 
      return resultCursor;
   }

总之,UriMatcher本质上是一个文本过滤器,用在contentProvider中帮助我们过滤,分辨出查询者想要查询哪个数据表。

下面讲解一下Uri自带的解析方法.

假如在ContentResolver中执行插入操作:

ContentResolver contentresolver=new ContentResolver();
//参数1:Uri
//参数2:插入值,这里设为空
//返回值,ContentProvider插入操作返回的Uri
Uri uri=contentresolver.insert(Uri.parse("content://com.deme.test/path?name=a,age=1,gender='男'"),new ContentValues);
//拿到追加到ContentProvider插入操作返回的Uri的id
long id=ContentUri.parse(uri);

在ContentProvider的相应插入方法中解析传来的Uri

// 在插入方法中直接解析
 @Override
        public Uri insert(Uri uri, ContentValues values) {
//content://com.deme.test/path?name=a,age=1,gender='男'"
             //解析传来的uri
             String authority=uri.getAuthority();//拿到授权 即 com.demo.test
             String path=uri.getPath();//拿到路径 即 path
             String query=uri.getAuthority();//拿到查询条件 即name=a,age=1,gender='男'
             String name=uri.getQueryParameter("name");//拿到姓名的字符即 a
             String age=uri.getQueryParameter("age");
             String gender=uri.getQueryParameter("gender");
             ContentValues v=new ContentValues();
             v.put("name",name);
             v.put("age",age);
             v.put("gender",gender);
            //向数据库中插入从contentResolver传来的数据,返回id
             int id=db.insert("表名"null,value);
            //通过ContentUris拼接搭配uri后民面返回
            Uri ReturnuUri=ContentUris.withAppendedId(uri,id);
            //将id追加到uri后面
            Log.e("Tag","执行了contentprovider的insert操作"+ReturnuUri);
            //返回给contentResolver
            return ReturnuUri;
    }

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值