UriMatcher类
在ContentProvider中,该类主要用来帮助匹配相对应的URI。
1. 构造函数:创建URI树的根节点
a) Public UriMatcher():默认根节点编码为-1;
b) Public UriMatcher(int code):code参数表示指定根节点的编码。
2. 方法
a) Public void addURI(String authority, String path, int code)
添加一个用于匹配的URI,当匹配成功时则code。URI可以是精确的字符串,uri中带有*表示可匹配任意text,#表示只能匹配数字。
Authority:用于匹配的域名;
Path:匹配路径,*表示text的占位符,#表示使用数字的占位符;
Code:当使用匹配成功后返回code,值需要大于0,否则抛出IllegalArgument异常。
此方法将authority按照”/”进行拆分,然后将拆分后的每一部分保存到UriMatcher类型的ArrayList中;在添加的时候会判断当前authority是否已经添加过,若已加则break;若未添加过,则判断是否含有”#”则将其标识成1代表域名后面跟随的是数字;”*”标识成2,代表域名后面跟随的是文本;0代表后面没有跟随数据;最后创建一个新的UriMatcher对象添加到集合中。
b) Public int match(Uri uri)
尝试在url中匹配相对应的路径
Uri:指定需要匹配的url;
返回值:在使用addURI时产生的code,若没有匹配则返回-1。
使用uri. getPathSegments()获取uri中各段存入list中,若list size为0或uri的Authority为null则返回默认值(此默认值在new时指定,若为指定则为-1);
然后遍历ArrayLis<UriMatcher>进行匹配uri。
参考源码:
/* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import android.net.Uri;
public class UriMatcher
{
public static final int NO_MATCH = -1;
/***
*
* Creates the root node of the URI tree.
*
*
*
* @param code
* the code 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 to return when this URI is
*
* matched. URI nodes may be exact match string, the token "*"
*
* that matches any text, or the token "#" that matches only
*
* numbers.
*
*
*
* @param authority
* the authority to match
*
* @param path
* the path to match. * may be used as a wild card for
*
* any text, and # may be used as a wild card for numbers.
*
* @param code
* the code that is returned when a URI is matched
*
* against the given components. Must be positive.
*/
public void addURI(String authority, String path, int code){
if (code < 0) {
throw new IllegalArgumentException("code " + code
+ " is invalid: it must be positive");
}
String[] tokens = path != null ? PATH_SPLIT_PATTERN.split(path) : null;
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("#")) {
//mWhich=1
child.mWhich = NUMBER;
} else if (token.equals("*")) {
//mWhich=2
child.mWhich = TEXT;
} else {
//mWhich=0
child.mWhich = EXACT;
}
child.mText = token;
node.mChildren.add(child);
//node = child;
node = child;
}
}
//node.mCode = code;
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 match against.
*
*
*
* @return The code for the matched node (added using addURI),
*
* or -1 if there is no matched node.
*/
public int match(Uri uri){
final List<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) {
case EXACT:
if (n.mText.equals(u)) {
node = n;
}
break;
case NUMBER:
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;
case TEXT:
node = n;
break;
}
if (node != null) {
break;
}
}
if (node == null) {
return NO_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 String mText;
private final ArrayList<UriMatcher> mChildren;
}