ContentProvider初阶Cookbook

来源:互联网 发布:金额分摊除不尽 算法 编辑:程序博客网 时间:2024/05/22 17:11
在Android世界里,ContentProvider将数据存储抽象成了类似SQL的形式,通过insert, delete, update, query等接口实现对数据的增删改查。通过ContentProvider,其所在应用程序和其他应用程序都可以通过URI访问数据源中的内容。被ContentProvider封装的数据源理论上可以是任何东西,但最常见的仍然是数据库。

构建一个ContentProvider最基本的流程如下:

一、元数据

包括整个数据源的元数据和各数据表格的元数据。对于整个数据源,需要提供的元数据包括其URI的authority部分、数据库名、数据表名、版本等等。对于数据表,应实现BaseColumn接口(以便获得如_id在内的默认列名),并在其中存放表名、MIME Type、URI等。

二、数据库访问类

这个类应该继承自SQLiteOpenHelper,一般作为ContentProvider具体类的内部类,并且ContentProvider需要持有它的引用。需要实现三个函数。
  1. 构造函数:至少要向父类型的构造函数传递数据库名、版本和Context等内容。
  2. onCreate:传入参数是一个SQLiteDatabase实例,可再次执行SQL语句创建数据表。(SQLiteDatabase.execSQL)
  3. onUpgrade:当版本升级的时候,参数包括数据库的实例、旧版本和新版本,通过增加列等手段来更新数据库的结构。最简单粗暴的方式,就是把已有内容删除,调用onCreate重新建立。
三、ContentProvider的实现类

这个类应该继承自ContentProvider。在其中需要实现如下内容:
  1. 列映射:将数据库中的列做一层抽象,保存在静态的Map<String, String>中。
  2. URI匹配:创建一静态UriMatcher对象,将合法的URI存入。它仍是类似字典的结构,将URI关联到一个整型常量,以供别处使用。
  3. onCreate:在ContentProvider首次被访问是调用。可选择在此创建SQLiteOpenHelper类的实例,但是官方文档中提倡将创建数据库的内容延后操作。
  4. getType:从URI得MIME type的方法。【*】
  5. query: 【**】根据不同的URI,尝使用SQLiteQueryBuilder类辅助查询。(新建对象后,调用SQLiteQueryBuilder.setTables, ~.setProjectionMap, ~.appendWhere等等)。而后从SQLiteOpenHelper字段中获取可读数据库对象,用qb.query方法执行查询。查询的结果通过Cursor对象返回。
  6. insert: 除了URI之外,还需要检查输入的ContentValues对象(键值对)是否完整。而后获取可写的数据库对象,调用其insert方法。如果插入成功,将返回新插入内容的URI,此时应调用getContext().getContentResolver().notifyChange()来通知数据源的观察者。
  7. delete, update: 类似insert,重点在于要根据不同类型的URI采取不同的策略进行删改。此外,这两个方法会返回受到影响的数据记录的数量。
四、在AndroidManifest.xml中声明

在provider标签中,必须要有
            android:authorities="ContentProvider对应的URI的authority段"
            android:name="ContentProvider的类型名"

五、使用ContentProvider

我的理解是,ContentProvider像一个提供数据的服务器。在Activity中,如果想使用某个ContentProvider,应通过URI、以ContentResolver作为客户端进行访问。为防止ANR的出现,应该使用异步方式访问数据源,如继承AsyncQueryHandler类型。对于查询操作的结果,可以通过ListView、CursorAdatper等之类型的配合来呈现给UI。

注释:
【*】其最常见的用途并非直接在ContentProvider中使用,而是在隐式启动Activity的时候。有时声明Activity时在AndroidManifest.xml文件中指定<data android:mimeType="someType">标签。这种情况下,尝试启动Activity时传入的Intent对象的data字段一 般是一个URI,系统就可以通过getType()方法找到对应的MIME Type来匹配相应的Activity。
【**】增、改、查诸方法,均需要解析给定的URI,用前面已经设置好的UriMatcher来判定URI对象的种类。
原创粉丝点击