楚云之南

先解决问题再写代码

Android Content Provider

ContentProvider作为Android应用之间共享数据的桥梁,为共享数据提供了一个统一的访问方式(一套统一的接口)。

URI

在Android中大量使用URI作为资源定位标识,它主要由 scheme host(authority) path params组成。例如我们有如下的一个Content Provider的URI如下:

content://www.chuyun923.com/books/10086/title/firstWord

其中content,是Android为Content Provider规定的scheme; PATH(books/10086/title/firstWord)可以直接表示用来操作的业务,表示书籍_ID=10086的书名的第一个单词。注意,我们可以在URI中定义各种奇葩的PATH来描述业务,但是的最终解释权归Content Provider的定义

既然我们可以指定一些PATH表示业务,那么Content Provider必然需要去解析各种PATH,然后提供各种匹配的处理逻辑,此时,UriMatcher应运而生。

UriMatcher

对一个给定的Uri进行HOST和PATH的匹配,而Scheme不在考虑范围。对于PATH的匹配主要是挨个去比较各个PATH参数是否相等。

使用UriMatcher,首先需要给它配置一些配置URI,以及映射的int

    private static final UriMatcher uriMatcher;
    static{
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI("net.manoel.provider.Books", "books", 1);
        uriMatcher.addURI("net.manoel.provider.Books", "books/#/title", 2);
        uriMatcher.addURI("net.manoel.provider.Books","books/#/title/firstword",3);
    }

这里配置了三个业务PATH,第一个表示整个books整个表。第二URI表示指定Id的书名,第三个表示指定id的书名的首单词。

那么, books/12/title将匹配第二个,在Content Provider收到这个URI时,可以使用UriMatcher得到2。 UriMatcher为URI提供了两种通配符 #代表数字;*代表任意字符。

需要注意一点的是UriMatcher进行匹配,会受到addURI的先后顺序影响。

如:uriMatcher按以下顺序添加:

*/#
#/*

那么 9/title将不能获得匹配,是不是很奇怪?

*/#/#
*/*/*

books/10/title也不能被匹配。

在匹配PATH是挨个参数进行,一旦一个路径参数被匹配,那么它就不会更换。 以books/10/title来说,匹配第一个patten的第一个参数 * 通过,10 匹配 #也通过,title不能匹配#,那么此时进行第二个patten的匹配。那么第二个patten必须满足*/#开头,否则就算是 */*也不能通过。