Android开发指导文档(译)--content provider(二)

创建一个Content Provider

要创建一个content provider你应该:

  • 建立一个存储数据的系统。多数的content providerAndroid的文件存储方法或SQlite数据库来存储数据,但是你可以用任何你想用的方法存储。Android提供了SQLiteOpenHelper类来帮助你创建一个数据库以及SQLiteDatabase来管理它。
  •  继承ContentProvider类来提供对数据的访问
  • manifest文件(AndroidManifest.xml)中为你的应用程序声明这个content provider

 

继承ContentProvider

要实现6ContentProvider类中声明的抽象方法:query() insert()  update()  delete()  getType()  onCreate() 

query() 方法必须返回一个可以遍历请求的数据的Cursor对象。Cursor本身是个接口,但是Android提供了一些你可使用的现成的Cursor对象。比如说,SQLiteCursor可以在SQLite数据库中存储的数据上迭代。你可以通过SQLiteDatabase类的query()方法获得该Cursor。还有其他的Cursor实现—如为没有存储在数据库中的数据准备的MatrixCursor

       因为这些ContentProvider方法可以在不同的进程和线程中使用各种ContentResolver对象调用,所以它们必须被实现为线程安全的。

       当要数据改变时,你也许同样会调用ContentResolver.notifyChange()来通知listener

       在定义子类之后,还有其它的步骤:

  •  定义一个public static final Uri CONTENT_URI。这是一个代表你的content provider持有的全content: URI字符串,你必须给其定义一个唯一的值。最好的方法是使用content providerfully-qualified类名(小写)。比如,一个TransportationProvider类的URI可以这样定义:

public static final Uri CONTENT_URI = Uri.parse("content://com.example.codelab.transportationprovider");  

 

如果这个provider还有子表,也要为每个子表定义CONTENT_URI常量。这些常量必须有相同的authority,只有path不同,比如:

content://com.example.codelab.transportationprovider/train 
content://com.example.codelab.transportationprovider/air/domestic 
content://com.example.codelab.transportationprovider/air/international

  •  定义content provider将要返回给用户的列的名字。如果你使用了底层的数据库,这些列名通常与SQL数据库列名相同。同样是声明为public static字符串常量,用户可以使用它们来指明要查询的列。

确保要提供一个整型的列,列名为"_id"(常量为_ID)作为记录的ID。必须有这个字段。如果你使用SQLite数据库,_ID应该是下面的类型:

INTEGER PRIMARY KEY AUTOINCREMENT

AUTOINCREMENT是可选的,但是没有它,SQLIte增加一个ID计数器字段来记录最大记录数的下一个值(?)。如果你删除了最后的一行,添加的下一行将会与删除的一行有相同的IDAUTOINCREMENT 可以让SQLite来处理ID的增长。

  •  备注好列的每一种数据类型,用户需要它来读取数据。
  •  如果你要处理一个新的数据类型,你必须声明一个新的MIME类型来作为你实现ContentProvider.getType()的返回。这个类型部分取决于提交给getType()content:URI是否限制对具体记录的请求。对单个记录有一种形式,对多个记录又有另一种形式。用Uri的方法来确定什么将被请求。下面是每种类型的一般格式:

对单个记录:  vnd.android.cursor.item/vnd.yourcompanyname.contenttype

例如:请求列车记录122有这样的URI:content://com.example.transportationprovider/trains/122

会返回这个MIME类型:vnd.android.cursor.item/vnd.example.rail

 对多个记录:vnd.android.cursor.dir/vnd.yourcompanyname.contenttype

例如:所有列车的请求URI:content://com.example.transportationprovider/trains

会返回这个MIME类型:vnd.android.cursor.dir/vnd.example.rail

  

  •  如果你要公布因太大而不能放入表里的二进制数据,公布(expose)给用户的数据的的字段应该包含content:URI字符串。这是让用户可以利用数据文件的字段。这个记录也应该有另一个字段,名为_data"来列出设备上那个文件的路径。这个字段不打算由用户读取,而是供ContentReslover使用。用户只要在user-facing 的字段调用

       ContentResolver.openInputStream()方法。ContentResolver会请求"_data"字段获得那条记录。因为它有比用户高的权限,所以它可以直接访问文件并为用户返回读取的结果。

 

声明content provider

       要让Android系统知道你开发的content provider,你应该在AndroidManifest.xml文件中用 <provider> 元素声明。未声明的content provider不可用。

       <provider>元素name属性是ContentProvider子类的全名。authorities 属性是标识providerURI中的authority部分。比如,ContentProvider子类如果是AutoInfoProvider<provider> 元素或许如下:

<provider android:name="com.example.autos.AutoInfoProvider" android:authorities="com.example.autos.autoinfoprovider" . . . /> </provider>  

 

注意authorities 属性省略了content:URIpath部分。比如说,如果AutoInfoProvider控制着不同类型汽车或不同生产厂商的表格:

content://com.example.autos.autoinfoprovider/honda 
content://com.example.autos.autoinfoprovider/gm/compact 
content://com.example.autos.autoinfoprovider/gm/suv

它们的path不会在manifest中声明。Authority标识这个provider,而不是path;你的provider可以以你选的的任何方式来解释(interpretURIpath部分

       其他的< provider >属性可以设置读写数据的权限,为其提供一个图标或者文本来显示给用户,使provider可用或不可用等等。如果数据不需要在多个运行版本的content provider同步,multiprocess 属性设置为"true"。这会允许在每个客户端进程创建一个provider的实例,消除了执行IPC的需要。(IPC:进程间通信)

 

Content URI 总结:

这里是一个content URI的重要部分的概括:

 

A.        标准的前缀,指示数据由content provider控制。它永远不会被修改

B.        URIauthority 部分,它标识这个content provider。对于第三方应用程序,这一部分应该是一个fully-qualified类名(小写)来确保唯一。Authority< provider >元素的authorities 属性声明。

<provider android:name=".TransportationProvider" android:authorities="com.example.transportationprovider" . . . >  


 

 

 

你可能感兴趣的:(android,数据库,sqlite,存储,文档,Path)