解读Content Provider之一
综述Content providers是一个Android应用程序的主要部分,主要是为应用程序提供内容。它对数据进行封装然后通过单一的ContentResolver接口提供给应用程序。只有需要在多个应用程序间共享数据时,content provider才是必须的。例如:有多个应用程序(例如:打电话程序和发短信程序等等)都需要使用联系人的数据,因此我们必须将这些数据存放在content provider。如果不需要在多个应用程序易做图享数据,那么可以直接在应用程序中使用SQLiteDatabase。
当程序通过一个ContentResolver接口请求Content provider时,系统就会检查传递进来的URI的权限,并且将请求传递给拥有这些权限的content provider。content provider可以以任意的方式解析URI。UriMatcher类对于解析URIs是非常有帮助的。
对于content provider主要要实现的方法有如下几个:
onCreate():主要是初始化provider;
query(Uri, String[], String, String[], String):讲数据返回给它的调用者
insert(Uri, COntentValues):插入新的数据到content provider
update(Uri, COntentValues, String, String[]):更新content provider中的数据
delete(Uri, String, String[])删除content provider中的数据
getType(Uri):返回content provider中数据的MIME类型
数据存取方法(例如:insert(Uri, ContentValues)和update(Uri, ContentValues, String, String[]))可能会在同一时间被多个线程调用,并且是线程安全的。其他的方法(例如:onCreate())仅仅被程序的主线程调用,而且必须要避免在其中进行耗时的操作。具体的请看方法的描述。
对于ContentResolver将会自动的传给合适的ContentProvider实例,因此子类不需要担心夸进程调用的细节。
开发者指南
对于如何使用content provider的细节,请阅读Content Providers开发者指南。
下面是Content Providers开发者指南:
Content Providers存取数据,并且使这些数据对于所有的程序都是可用的。Android系统中并没有对任何程序都可使用的共同存储区域,因此,这是在多个应用程序间共享数据的唯一方法。
Android系统包含许多的对常见类型数据(音频、视频、图片以及个人联系信息等等)的content providers。你可以在android.provider包中看到一部分的content provider。你可以查询这个content provider中包含的数据(尽管对于其中的一部分数据,你必须要拥有合适的权限)。
如果你想让自己的数据对外部公开,你有两个选择:
1.你可以创建你自己的content provider(一个Content Provider子类)
2.你可以将自己的数据添加到已经存在的content provide,如果存在包含着和你想公开数据的相同类型数据的content provider,并且你拥有权限,你就可以将这些数据写入到这个content provider中。
这篇文档是介绍如何使用content provider。在简洁的讨论了一下基本后,这些讨论覆盖了如何查询一个content provider中的内容,如何修改一个content provider中包含的数据,如何为自己创建一个content provider。
Content Provider 基础知识
content provider如何存储数据是依赖于它的设计的。但是所有的content provider都实现了一个共同的接口用于查询provider并且返回结果--以及:添加,修改和删除数据等。
客户端不会直接使用这个接口,几乎都是通过ContentResolver对象。你可以通过实现在Activity中或其它应用程序组件中的getContentResolver()方法来获得ContentResolver.
ContentResolver cr = getContentResolver();
你可以通过ContentResolver的方法和感兴趣的content providers进行交互。
当一个查询操作初始化后,Android系统识别查询要进行的操作对象,并且确保它处于运行状态。系统实例化了所有的Contentprovider对象:你根本不需要进行这样的操作。实际上,你从来就不会直接和ContentProvider打交道。实际上,对于每一种ContentProvider,系统仅仅有一个实例。但是这一个ContentProvider实例却可以和处于多个程序、多个进程中的ContentResolver对象进行通信。多个进程间的交互是通过ContentResolver类和ContentProvider类进行的。
数据模型
Content providers是像数据库中的表的模型一样暴露自己所包含的数据,每一行都是一条记录,每一列都是一个特定的类型并且有特定的意义。例如:联系人的信息以及他们的电话号码就可能像如下一样存储:
在表中的每一条记录都含有是个数值型的_ID域,每一条记录的该域都是唯一的,用以标示这条记录。IDs可以用来匹配关联表中的记录,例如:在一个表中找到一个联系人的电话号码,在另一个表中找到该联系人的图片。
查询操作可以返回一个Cursor对象,通过这个Cursor对象你可以从一条记录移动到另一条记录,从一个列移动到另一个列来读取每个列值。
对于每一种类型的数据,他都有特定的方法读取。因此,要读取一个域的值,你必须要知道这个域的值的数据类型(关于这方面的详细内容会在查询操作以及Cursor对象中介绍)。
URIs
每一个content provider都暴露了一个公共的URI(包装成一个Uri对象)用来唯一标示它包含的数据集。对于那些包含多数据集(多个表)的content provider它会为每一个数据集提供一个URI。所有由provider暴露的URIs都是以字符串"content://"开头的。"content:"表明这个数据集是由一个content provider提供的。
如果你定义了一个content provider,那么为它的URI定义一个常量是一个比较好的做法,这样就可以简化客户端的编程并且使得将来的更新更加的彻底。Android随着平台一起为所有的providers定义了CONTENT_URI这个常量,例如:对于联系人电话号码的表的URI和存储联系人图片的表的URI(两者都是被Contacts content provider控制)分别如下:
android:provider.Contacts.Phone.CONTENT_URI
android:provider.Contacts.Photos.CONTENT_URI
URI常量在所有与content provider的交互操作中都会被使用到。每一个ContentResolver的方法的第一个参数都是URI。它代表着ContentResolver将会与哪一个provider通信,竟会操作provider中的哪一个表。
查询一个Content Provider
你需要三方面的信息来查询一个xontent provider:
1.标示provider的URI;
2.你希望接收的数据域的名称;
3.你希望操作的数据域的数据类型。
如果你是查询特定的记录,那么你还需要唯一标示这条记录的ID。
执行查询操作
要查询一个content provider,你将会使用到ContentResolver.query(0方法或者是Activity.managedQuery()方法。这两个方法使用同样的参数,都返回一个Cursor对象。然而,managedQuery()方易做图使得由activity来管理返回的Cursor对象的生命周期。一个被管理的Cursor对象必须处理所有的细节,例如:在activity处于暂停状态时就要卸载自己,当activity处于重启时,又要开始执行查询操作。 你可以调用Activity.startManagingCursor()方法来管理一个还未被管理的Cursor对象。
query()和managedQuery()方法的第一参数都是provider的URI——CONTENT_URI常量标示了一个特定的ContentProvider以及其数据集。
要严格的查询到一条记录,你必须追加记录的_ID到URI上——也就是,将代表ID的字符串放置在URI的最后字段。例如:如果ID是23,那么URI就如下所示:
content://. . . ./23
这里有一些帮助的方法,特别是ContentUris.withAppendedId()和Uri.withAppendedPath()方法,他们使得追加一个ID到URI上变得更加容易。这两个静态方法都返回追加了ID的Uri对象。因此,如果你想在联系人的数据库中查找到标示为23的这条记录,你可以像下面这样构建一个查询器:
import android.provider.Contacts.People;
import android.content.ContentUris;
import android.net.Uri;
import android.database.Cursor;
// Use the ContentUris method to produce the base URI for the contact with _ID == 23.
Uri myPerson = ContentUris.withAppendedId(People.CONTENT_URI, 23);
// Alternatively, use the Uri method to produce the base URI.
// It takes a string rather than an integer.
Uri myPerson = Uri.withAppendedPath(People.CONTENT_URI, "23");
// Then query for this specific record:
Cursor cur = managedQuery(myPerson
补充:移动开发 , Android ,