原文地址:http://blog.csdn.net/wcs542882916
package android.content;
import android.net.Uri;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
/**
Utility class toaid in matching URIs in content providers.
在contentproviders里帮助匹配URIs的实用类
<p>To use this class, build up a tree of<code>UriMatcher</code> objects.
For example:
使用这个类建立UriMatcher对象的一个树,一下是UriMatcher的用法
<pre>
private static final int PEOPLE = 1;
private static final int PEOPLE_ID =2;
private static final intPEOPLE_PHONES = 3;
private static final intPEOPLE_PHONES_ID = 4;
private static final intPEOPLE_CONTACTMETHODS = 7;
private static final intPEOPLE_CONTACTMETHODS_ID = 8;
private static final intDELETED_PEOPLE = 20;
private static final int PHONES = 9;
private static final int PHONES_ID =10;
private static final intPHONES_FILTER = 14;
private static final intCONTACTMETHODS = 18;
private static final intCONTACTMETHODS_ID = 19;
private static final int CALLS = 11;
private static final int CALLS_ID =12;
private static final intCALLS_FILTER = 15;
private static final UriMatcher sURIMatcher= new UriMatcher(UriMatcher.NO_MATCH);
static
{
sURIMatcher.addURI("contacts", "people", PEOPLE);
sURIMatcher.addURI("contacts", "people/#",PEOPLE_ID);
sURIMatcher.addURI("contacts", "people/#/phones",PEOPLE_PHONES);
sURIMatcher.addURI("contacts", "people/#/phones/#",PEOPLE_PHONES_ID);
sURIMatcher.addURI("contacts","people/#/contact_methods", PEOPLE_CONTACTMETHODS);
sURIMatcher.addURI("contacts","people/#/contact_methods/#", PEOPLE_CONTACTMETHODS_ID);
sURIMatcher.addURI("contacts", "deleted_people",DELETED_PEOPLE);
sURIMatcher.addURI("contacts", "phones", PHONES);
sURIMatcher.addURI("contacts", "phones/filter/*",PHONES_FILTER);
sURIMatcher.addURI("contacts", "phones/#",PHONES_ID);
sURIMatcher.addURI("contacts", "contact_methods",CONTACTMETHODS);
sURIMatcher.addURI("contacts", "contact_methods/#",CONTACTMETHODS_ID);
sURIMatcher.addURI("call_log", "calls", CALLS);
sURIMatcher.addURI("call_log", "calls/filter/*",CALLS_FILTER);
sURIMatcher.addURI("call_log", "calls/#", CALLS_ID);
}
</pre>
<p>Starting from API level{@linkandroid.os.Build.VERSION_CODES#JELLY_BEAN_MR2}, paths can start
with a leading slash. For example:
<pre>
sURIMatcher.addURI("contacts", "/people", PEOPLE);
</pre>
<p>Then when you need to match against a URI,call{@link #match}, providing
the URL that youhave been given. You can use the resultto build a query,
return a type,insert or delete a row, or whatever you need, without duplicating
all of the if-else logicthat you would otherwise need. Forexample:
<pre>
public String getType(Uri url)
{
int match = sURIMatcher.match(url);
switch (match)
{
case PEOPLE:
return"vnd.android.cursor.dir/person";
case PEOPLE_ID:
return"vnd.android.cursor.item/person";
... snip...
return"vnd.android.cursor.dir/snail-mail";
case PEOPLE_ADDRESS_ID:
return"vnd.android.cursor.item/snail-mail";
default:
return null;
}
}
</pre>
instead of:
<pre>
public String getType(Uri url)
{
List<String>pathSegments = url.getPathSegments();
if (pathSegments.size() >= 2) {
if("people".equals(pathSegments.get(1))) {
if (pathSegments.size() == 2) {
return"vnd.android.cursor.dir/person";
} else if (pathSegments.size()== 3) {
return"vnd.android.cursor.item/person";
... snip...
return"vnd.android.cursor.dir/snail-mail";
} else if (pathSegments.size()== 3) {
return"vnd.android.cursor.item/snail-mail";
}
}
}
return null;
}
</pre>
*/
public class UriMatcher
{
public static final int NO_MATCH = -1;
/**
* Creates the root node of the URI tree.
* 创建URI树的根节点
* @param code thecode to match for the root URI
*/
public UriMatcher(int code)
{
mCode = code;
mWhich = -1;
mChildren = new ArrayList<UriMatcher>();
mText = null;
} private UriMatcher()
{
mCode = NO_MATCH;
mWhich = -1;
mChildren = new ArrayList<UriMatcher>();
mText = null;
}
/**
* Add a URI to match, and the code toreturn when this URI is
* matched. URI nodes may be exact matchstring, the token "*"
* that matches any text, or the token"#" that matches only
* numbers.
* <p>
* Starting from API level {@linkandroid.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
* this method will accept leading slash inthe path.
*
* @param authoritythe authority to match
* @param path thepath to match. * may be used as a wild card for
* any text, and # may be used as a wildcard for numbers.
* @param code thecode that is returned when a URI is matched
* against the given components. Must bepositive.
*
* 添加需要匹配的URI,当URI匹配的时候返回code。
* URI节点可能会精确的匹配字符串,标记“*”匹配任何text,标记“#”仅仅匹配数字。
* 从 API level 18(JELLY_BEAN_MR2)开始,这个方法中的path参数接受正向斜线。
* path路径前的“/”可有可无eg:sURIMatcher.addURI("contacts", "people", PEOPLE);
* code这个参数必须是正数,大于等于0
*/
publicvoid addURI(String authority, String path,int code)
{
if (code <0) {
throw new IllegalArgumentException("code " + code +" isinvalid: it must be positive");
}
String[] tokens = null;
if (path !=null) {
String newPath = path;
// Strip leading slash if present.
if(path.length() > 0 && path.charAt(0) =='/') {
newPath = path.substring(1);
}
tokens = PATH_SPLIT_PATTERN.split(newPath);
}
int numTokens =tokens !=null ? tokens.length : 0;
UriMatcher node = this;
for (int i = -1; i < numTokens; i++) {
String token = i < 0 ? authority: tokens[i];
ArrayList<UriMatcher>children = node.mChildren;
int numChildren= children.size();
UriMatcher child;
int j;
for (j = 0; j< numChildren; j++) {
child = children.get(j);
if(token.equals(child.mText)) {
node = child;
break;
}
}
if (j ==numChildren) {
// Child not found, create it
child = new UriMatcher();
if(token.equals("#")) {
child.mWhich =NUMBER;
} elseif (token.equals("*")) {
child.mWhich =TEXT;
} else {
child.mWhich =EXACT;
}
child.mText = token;
node.mChildren.add(child);
node = child;
}
}
node.mCode = code;
}
/**
* 还不知道用法,以后去了解
*/
static final Pattern PATH_SPLIT_PATTERN =Pattern.compile("/");
/**
* Try to match against the path in a url.
*
* @param uri The url whose path we will matchagainst.
*
* @return The code for the matched node (added using addURI),
* or -1 if there is no matched node.
*
* 如果匹配则返回添加时的code,否则返回-1
*/
publicint match(Uri uri)
{
finalList<String> pathSegments = uri.getPathSegments();
final int li = pathSegments.size();
UriMatcher node = this;
if (li == 0&& uri.getAuthority() ==null) {
return this.mCode;
}
for (int i=-1; i<li; i++) {
String u = i < 0 ?uri.getAuthority() : pathSegments.get(i);
ArrayList<UriMatcher> list =node.mChildren;
if (list ==null) {
break;
}
node = null;
int lj =list.size();
for (int j=0; j<lj; j++) {
UriMatcher n = list.get(j);
which_switch:
switch (n.mWhich) {
caseEXACT:
if (n.mText.equals(u)) {
node = n;
}
break;
caseNUMBER:
int lk = u.length();
for (int k=0; k<lk; k++) {
char c = u.charAt(k);
if (c <'0' || c > '9') {
break which_switch;
}
}
node = n;
break;
caseTEXT:
node = n;
break;
}
if (node !=null) {
break;
}
}
if (node ==null) {
returnNO_MATCH;
}
}
return node.mCode;
}
private static final int EXACT = 0;
private static final int NUMBER = 1;
private static final int TEXT = 2;
private int mCode;
private int mWhich;
private StringmText;
privateArrayList<UriMatcher>mChildren;
}