在对我之前的一个问题的回答中,有人表示Android类UriMatcher中存在一些固有的缺陷(缺乏更好的词)。任何人都可以通过UriMatcher查明已知问题吗?我正在设计一个依赖于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)
在上一个问题(前面提到过)中,建议我将违规的Uri移到UriMatcher.put(String,int)调用的顶部。这解决了以前的问题(让我口中的味道很糟糕)。使用此代码尝试相同的解决方案会导致当前的第一个Uri(JOBNAME_SINGLE_URI)无法识别。我很确定问题不在我的代码中(我已经设法创建一个有效的ContentProvider利用Uris并在此问题之前调试它们的所有问题),而是在Android中使用Uri匹配的问题
更新:
public final static String AUTHORITY = "dsndata.sds2mobile.jobprovider";
示例Uri:
内容://dsndata.sds2mobile.jobprovider/SDS2MobileDemo/reverse/C_1
答案 0 :(得分:35)
有三条规则没有详细记录,但对于理解UriMatcher的匹配机制至关重要:
以下是使用以下网址的一些示例:content://dsndata.sds2mobile.jobprovider/SDS2MobileDemo/reverse/C_1
前两条规则很容易理解:
第三条规则有点难以理解。 如果按照以下确切顺序添加以下Uris:
然后它将找不到匹配,因为它转换为以下(伪)代码:
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 / *路径走下去...... 另外很明显,将* / reverse / *移动到顶部不是解决方案,因为所有其他不以*开头的模式将不再匹配。 只要不知道哪种模式应与哪种Uris相匹配,真的无法确定正确的解决方案是什么。
答案 1 :(得分:2)
uriMatcher.addURI(JobMetaData.AUTHORITY, "*/reverse/*", REVERSE_URI);
应该有效
修改
以下示例有效,请尝试使用您的值并检查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)) ;
}
答案 2 :(得分:1)
我们可以使用Regex作为环顾解决方案。
这是表达式
https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?
它应该有用!
答案 3 :(得分:0)
我刚遇到UriMatcher问题并解决了它。确保你总是把外卡完全匹配。如果你没有,UriMatcher代码会沿着通配符路径向下移动,如果它选择了错误的路径,则不会返回。
不幸的是,我没有看到你的情况究竟出了什么问题。我会尝试将JOBNAME_COLLECTION_URI移到最顶层或将其删除;我想知道这是否会导致问题。