Android的UriMatcher问题

在回答我之前的一个问题时,有人指出Android类UriMatcher中固有的一些片状(缺less一个更好的词)。 任何人都可以用UriMatcher查明已知的问题吗? 我正在devise一个内容提供者,依赖于UriMatcher来正确匹配我的Uris(而不是我认为是错误的)。 有没有解决已知的问题? 还是有更好的匹配Uris的策略?

例:

这里是设置我的UriMatcher的代码

private static final int MEMBER_COLLECTION_URI = 1; private static final int MEMBER_SINGLE_URI = 2; private static final int SUBMATERIAL_COLLECTION_URI = 3; private static final int SUBMATERIAL_SINGLE_URI = 4; private static final int JOBNAME_COLLECTION_URI = 5; private static final int JOBNAME_SINGLE_URI = 6; private static final int ALL_MEMBERS_URI = 7; private static final int ALL_SUBMATERIAL_URI = 8; static { //return the job and fab for anything matching the provided jobName // JobNames/jobName uriMatcher.addURI(JobMetaData.AUTHORITY, "JobNames/*/", JOBNAME_SINGLE_URI); //return a collection of members // jobName/member/attribute/value uriMatcher.addURI(JobMetaData.AUTHORITY, "*/member/*/*/", MEMBER_COLLECTION_URI); //return a single member // jobName/member/memberNumber uriMatcher.addURI(JobMetaData.AUTHORITY, "*/member/*/", MEMBER_SINGLE_URI); //return a collection of submaterial // jobName/submaterial/attribute/value uriMatcher.addURI(JobMetaData.AUTHORITY, "*/submaterial/*/*", SUBMATERIAL_COLLECTION_URI); //return a single piece of submaterial // jobName/submaterial/GUID //GUID is the only way to uniquely identify a piece of submaterial uriMatcher.addURI(JobMetaData.AUTHORITY, "*/submaterial/*", SUBMATERIAL_SINGLE_URI); //Return everything in the member and submaterial tables //that has the provided attribute that matches the provided value // jobName/attribute/value //not currently used uriMatcher.addURI(JobMetaData.AUTHORITY, "JobNames/", JOBNAME_COLLECTION_URI); //return all members in a job uriMatcher.addURI(JobMetaData.AUTHORITY, "*/members/", ALL_MEMBERS_URI); } 

添加另一个Uri:

 private static final int MEMBER_COLLECTION_URI = 1; private static final int MEMBER_SINGLE_URI = 2; private static final int SUBMATERIAL_COLLECTION_URI = 3; private static final int SUBMATERIAL_SINGLE_URI = 4; private static final int JOBNAME_COLLECTION_URI = 5; private static final int JOBNAME_SINGLE_URI = 6; private static final int ALL_MEMBERS_URI = 7; private static final int ALL_SUBMATERIAL_URI = 8; //ADDITIONAL URI private static final int REVERSE_URI = 9; static { //return the job and fab for anything matching the provided jobName // JobNames/jobName uriMatcher.addURI(JobMetaData.AUTHORITY, "JobNames/*/", JOBNAME_SINGLE_URI); //return a collection of members // jobName/member/attribute/value uriMatcher.addURI(JobMetaData.AUTHORITY, "*/member/*/*/", MEMBER_COLLECTION_URI); //return a single member // jobName/member/memberNumber uriMatcher.addURI(JobMetaData.AUTHORITY, "*/member/*/", MEMBER_SINGLE_URI); //return a collection of submaterial // jobName/submaterial/attribute/value uriMatcher.addURI(JobMetaData.AUTHORITY, "*/submaterial/*/*", SUBMATERIAL_COLLECTION_URI); //return a single piece of submaterial // jobName/submaterial/GUID //GUID is the only way to uniquely identify a piece of submaterial uriMatcher.addURI(JobMetaData.AUTHORITY, "*/submaterial/*", SUBMATERIAL_SINGLE_URI); //Return everything in the member and submaterial tables //that has the provided attribute that matches the provided value // jobName/attribute/value //not currently used uriMatcher.addURI(JobMetaData.AUTHORITY, "JobNames/", JOBNAME_COLLECTION_URI); //return all members in a job uriMatcher.addURI(JobMetaData.AUTHORITY, "*/members/", ALL_MEMBERS_URI); //ADDITIONAL URI uriMatcher.addURI(JobMetaData.AUTHORITY, "*/reverse/*", REVERSE_URI); } 

而最后一个Uri不被识别使用:uriMatcher.match(uri)

在上一个问题中(前面提到过),build议将违规Uri移动到调用UriMatcher.put(String,int)的顶部。 这解决了以前的问题(使我的口感不好)。 用这个代码尝试相同的解决scheme导致当前第一个Uri(JOBNAME_SINGLE_URI)无法识别。 我相当确定这个问题不在我的代码中(我已经设法利用Uris创build一个可用的ContentProvider,并在这个问题之前debugging了它们的所有问题),而是在Android中与Uri匹配的问题。

更新:

 public final static String AUTHORITY = "dsndata.sds2mobile.jobprovider"; 

样本Uri:
内容://dsndata.sds2mobile.jobprovider/SDS2MobileDemo/reverse/C_1

Solutions Collecting From Web of "Android的UriMatcher问题"

有三条规则没有很好的logging,但对于理解UriMatcher的匹配机制至关重要:

  1. UriMatcher试图将整个Uri与该模式进行匹配。 很像java.util.regex.Matcher的matches()方法,只有当整个区域序列匹配匹配器的模式时才返回true(与部分匹配返回true的find()方法相比)。
  2. 通配符仅适用于一个path段,这意味着*或SDS2MobileDemo / *将永远不会匹配SDS2MobileDemo / reverse / C_1,而是* / * / *或* / * / C_1。
  3. 一旦findpath段的匹配,就不会find该特定path段的任何替代匹配。

以下是使用以下url的一些示例:content://dsndata.sds2mobile.jobprovider/SDS2MobileDemo/reverse/C_1

前两条规则很容易理解:

  • SDS2MobileDemo / * / *将匹配
  • * / reverse / *会匹配
  • * / *不匹配,因为它只匹配两个path段
  • SDS2MobileDemo不匹配,因为它只匹配一个path段

第三条规则有点难以理解。 如果您按以下顺序添加以下Uris:

  • * /错/ C_1
  • SDS2MobileDemo /反向/ C_1

那么它不会find一个匹配,因为它翻译成以下(伪)代码:

 if ("*".matches("SDS2MobileDemo")) { // tries to match the other parts but fails } else if ("SDS2MobileDemo".matches("SDS2MobileDemo")) { // will never be executed } 

如果您颠倒顺序(伪)代码变成:

 if ("SDS2MobileDemo".matches("SDS2MobileDemo")) { // tries to match the other parts and succeeds } else if ("*".matches("SDS2MobileDemo")) { // will never be executed } 

现在只要原来的问题。 SDS2MobileDemo / reverse / C_1将会被* / reverse / *匹配,但是不会比如JobNames / reverse / C_1,因为那个将会沿着JobNames / *path移动……另外,显然移动* / reverse / *这个解决scheme是因为所有不以*开始的其他模式都不会再匹配。 只要不知道哪种模式应该与哪个Uris相匹配,真的不知道正确的解决scheme。

唔….错别字? 似乎之后有一些空白/反向/

 uriMatcher.addURI(JobMetaData.AUTHORITY, "*/reverse/*", REVERSE_URI); 

应该pipe用

编辑

下面的例子工作,尝试与您的值,并检查您的LogCat窗口的警告

检查JobMetaData.AUTHORITY中的值。

 public static final String PROVIDER ="org.dummy.provider" ; public static void doTest() { testUri("content://"+PROVIDER +"/test/reverse/xb32") ; testUri("content://"+PROVIDER +"/JobNames/YES/") ; } private static void testUri(String pStr) { Uri uri = Uri.parse(pStr); Log.w("Test", "uri = " + pStr) ; int result = uriMatcher.match(uri) ; Log.w("Test", "result = " + result) ; List<String> list = uri.getPathSegments() ; for (int i = 0 ; i < list.size() ; i++) Log.w("Test", "Segment" + i + " = " + uri.getPathSegments().get(i)) ; } 

我们可以使用正则expression式作为解决scheme。

这是expression式

 https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)? 

它应该工作!

我遇到了一个UriMatcher问题并解决了它。 确保你总是把通配符完全匹配。 如果你不这样做,UriMatcher代码沿着通配符path走,如果select了错误的path则不会返回。

不幸的是,我不明白你的情况到底出了什么问题。 我会尝试将JOBNAME_COLLECTION_URI移到最顶端或将其移除; 我想知道这是否会造成问题。