Problems with Android's UriMatcher

前端 未结 4 1179
你的背包
你的背包 2020-12-13 20:36

In an answer to a previous question of mine someone indicated that there is some flakiness (for lack of a better word) inherent in the Android class UriMatcher. Can anyone p

4条回答
  •  天命终不由人
    2020-12-13 21:01

    There are three rules that aren't well documented but that are crucial to understanding the matching mechanism of UriMatcher:

    1. UriMatcher tries to match the entire Uri against the pattern. Much like the matches() method of java.util.regex.Matcher that returns true only if the entire region sequence matches the matcher's pattern (compared to the find() method that returns true for partial matches).
    2. Wildcards are applied to one path segment only, meaning * or SDS2MobileDemo/* will never match SDS2MobileDemo/reverse/C_1 but */*/* or */*/C_1 will.
    3. Once it finds a match for a path segment it won't find any alternative match for that particular path segment.

    Here are some examples using the following url: content://dsndata.sds2mobile.jobprovider/SDS2MobileDemo/reverse/C_1

    The first two rules are easy to understand:

    • SDS2MobileDemo/*/* will match
    • */reverse/* will match
    • */* won't match because it matches only two path segments
    • SDS2MobileDemo won't match because it matches only one path segment

    The third rule is a little harder to understand. If you add the following Uris in this exact order:

    • */wrong/C_1
    • SDS2MobileDemo/reverse/C_1

    then it won't find a match because that translates into the following (pseudo) code:

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

    If you reverse the order the (pseudo) code becomes:

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

    Now as far as the original question goes. SDS2MobileDemo/reverse/C_1 will get matched by */reverse/* but not e.g. JobNames/reverse/C_1 because that one will go down the JobNames/* path... Also it's clear that moving */reverse/* to the top isn't the solution because all other patterns not starting with * won't match any more. There's really no telling what the correct solution is as long as it's unknown which patterns should match which Uris.

提交回复
热议问题