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; }