在回答我的上一个问题时,有人指出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)。我相当确定问题不在我的代码中(我已经设法使用Uris创建了一个可用的ContentProvider并在此问题之前调试了所有问题),而是与Android中的Uri匹配有关的问题。
更新:
public final static String AUTHORITY = "dsndata.sds2mobile.jobprovider";
样本Uri:
内容://dsndata.sds2mobile.jobprovider/SDS2MobileDemo/reverse/C_1
最佳答案
以下三条规则没有得到很好的记录,但是对于理解UriMatcher的匹配机制至关重要:
这是一些使用以下URL的示例: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匹配,就真的无法确定什么是正确的解决方案。