原文:https://blog.csdn.net/herbert5069/article/details/7212675
ContentProvider是Android四大组件之一,网上也有不少关于它的文章,基本用法都可以查到,但关于UriMatcher在其中的作用,文章中都有例子,但我觉得还没有说清楚。
通用资源标志符(Universal Resource Identifier, 简称"URI");
Uri代表要操作的数据,Android上可用的每种资源-图像、视频片段等都可以用Uri来表示。
URI一般由三部分组成:
Android的Uri由以下三部分组成:"content://"、数据路径、标示ID
举例子,如:
实现query、insert.....方法都已经指定操作入口了,为何还要matcher uri,原来是解决多表等情况。
public void addURI (String authority, String path, int code)
这个方法是用来表示在 content provider 里面添加外部对其的匹配的规则,当 URI 被匹配的时候,就会返回 code 码, URI 节点可以精确的匹配字符串, "*" 号匹配任何的字符串 "#" 号只能匹配数字。[比如删除一条记录中 ID 往往是数字]
参数说明
authority : 授权, 就是 AndroidMainifest.xml 中的授权
path : 匹配路径(通常是一个表名)[* 可以作为匹配任意字符的通配符, # 可以作为匹配数字的通配符]。
【注意这里如果是单条记录,需要添加 /# 标示符】
--常量 UriMatcher.NO_MATCH 表示不匹配任何路径的返回码(-1)
//URI解析
//1.UriMatcher:在ContentProvider创建时,制定好规则
//当ContentResolver调用ContentProvider的操作方法(会传进来一个uri)
//在相应的操作ContentProvider利用匹配类去匹配uri,根据不同的uri给出不同的处理
UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
matcher.addURI("country", "america", 0);
matcher.addURI("country", "china", 1);
//假设传入的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中帮助我们过滤,分辨出查询者想要查询哪个数据表。
假如在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;
}