Android 内容提供器---创建内容提供器(设计内容资源标识(URI))

内容资源标识是标识提供器内数据的统一标识。内容资源标识包括完整的提供器的符合名(它的权限)和指向表或文件的名字(一个路径)。可选的ID部分指向一个表中独立的行。ContentProvider类的每个数据访问方法都要有一个内容资源标识做为参数,这样就允许你来决定要访问的表、行或文件。

设计权限

通常,提供器会有一个单一的权限作为它在Android内部的名字。要避免跟其他提供器的冲突,你应该使用互联网域所有权作为你的提供器权限的基础。因为这个建议对Android包名也是适用的,因此你能使用包含提供器的包的名的扩展来定义你的提供器的权限。例如,如果你的Android包名是com.example.<appname>,那么应该给你的提供器权限是com.example.<appname>.provider。

设计路径结构

通常,开发者通过把指向单个表的路径附加到权限中的方法来创建内容资源标识(URI)。例如,如果你有两个表:table1和table2,你把这两个表跟前面的例子的权限组合,就会产生以下内容资源标识:

com.example.<appname>.provider/table1和com.example.<appname>.provider/table2。路径不限于单一表的部分,不是每个路径级别都要有一个表。

处理内容资源标识ID

通过协议,提供器通过接受一个在URI的尾部携带行的ID值的内容资源标识的方法来提供对一个表中的单一行的访问。也可以同协议,提供器把这个ID值与表的_ID列进行匹配,并且针对匹配行执行请求访问。

这种协议有利于针对应用访问提供器采用共同的设计模式。应用执行针对这个提供器的查询,并且使用CursorAdapter对象把Cursor对象的结果显示在ListView对象中。CursorAdapter的定义要求在Cursor对象中要有一列是_ID.

用户从UI中显示的行中选择一行,以便查看或修改数据。应用获取从Cursor对象映射到ListView中的对应行,取得这行的_ID值,然后把这个_ID值附加到资源标识中并把这个访问请求发送给提供器,那么提供器就能够针对用户选中的行进行查询或修改。

内容资源标识模式

为帮助你对输入的内容资源标识选择合适动作,内容提供器API包括了协议类UriMatcher,它把内容资源标识模式映射成一个整数值。你能够在switch语句中使用这个整数值,给内容资源标识或跟特定模式匹配的资源标识选择需要的动作。

以下是资源标识(URI)中使用的通配符:

1. * :跟任意长度、任意有效的字符串匹配;

2. # :跟任意长度的数字字符串匹配。

做为设计和编码内容资源标识(URI)处理的一个例子,一个带有权限com.example.app.provider的提供器,能够识别下列指向表的资源标识:

1. content://com.example.app.provider/table1: 指向一个叫做table1的表;

2. content://com.example.app.provider/table2/dataset1: 指向一个叫做dataset1的表.

3. content://com.example.app.provider/table2/dataset2:指向一个叫做dataset2的表;

4. content://com.example.app.provider/table3:指向一个叫做table3的表。

这个提供器也识别那些在资源标识尾部追加了行ID的资源标识,例如:

content://com.example.app.provider/table3/1 指定了表table3中ID是1的行

以下内容资源标识模式也是可能的:

content://com.example.app.provider/*

这种模式可以跟提供器中任意资源标识匹配。

content://com.example.app.provider/table2/*:

content://com.example.app.provider/table3/#:

跟表table3中的某一行匹配,如

content://com.example.app.provider/table3/6

指定了匹配数据是表table3的ID是6的行

以下代码片段显示了UriMatcher中的方法是如何工作的。这段代码通过使用表资源标识模式content://<authority>/<path>和单行资源标识模式content://<authority>/<path>/<id>来区分处理表的资源标识和单行资源标识。

addURI()方法把权限和路径映射到一个整数值。Android.content.UriMatcher#match(Uri)match()方法给一个URI返回一个整数值,一个switch语句在查询整个表盒查询单行记录之间选择:

public class ExampleProvider extends ContentProvider {
...
    // Creates a UriMatcher object.
    private static final UriMatcher sUriMatcher;
...
    /*
     * The calls to addURI() go here, for all of the content URI patterns that the provider
     * should recognize. For this snippet, only the calls for table 3 are shown.
     */
...
    /*
     * Sets the integer value for multiple rows in table 3 to 1. Notice that no wildcard is used
     * in the path
     */
    sUriMatcher.addURI("com.example.app.provider", "table3", 1);

    /*
     * Sets the code for a single row to 2. In this case, the "#" wildcard is
     * used. "content://com.example.app.provider/table3/3" matches, but
     * "content://com.example.app.provider/table3 doesn't.
     */
    sUriMatcher.addURI("com.example.app.provider", "table3/#", 2);
...
    // Implements ContentProvider.query()
    public Cursor query(
        Uri uri,
        String[] projection,
        String selection,
        String[] selectionArgs,
        String sortOrder) {
...
        /*
         * Choose the table to query and a sort order based on the code returned for the incoming
         * URI. Here, too, only the statements for table 3 are shown.
         */
        switch (sUriMatcher.match(uri)) {


            // If the incoming URI was for all of table3
            case 1:

                if (TextUtils.isEmpty(sortOrder)) sortOrder = "_ID ASC";
                break;

            // If the incoming URI was for a single row
            case 2:

                /*
                 * Because this URI was for a single row, the _ID value part is
                 * present. Get the last path segment from the URI; this is the _ID value.
                 * Then, append the value to the WHERE clause for the query
                 */
                selection = selection + "_ID = " uri.getLastPathSegment();
                break;

            default:
            ...
                // If the URI is not recognized, you should do some error handling here.
        }
        // call the code to actually do the query
    }

另外一个类ContentUris给处理带有id部分的内容资源标识提供了便利的方法。这个类的Uri和Uri.Builder包含了解析既存的URI对象和创建新的URI对象的便利方法。

注:本人转载系个人觉得翻译的很好,值得收藏,且自己回头看着方便。

如有兴趣请访问作者官方博客http://blog.csdn.net/FireOfStar


你可能感兴趣的:(android)