`
zhouxin464585932
  • 浏览: 78998 次
  • 性别: Icon_minigender_1
  • 来自: 南京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

ContentProvider的一个例子

阅读更多

ContentProvider的一个例子

转自:http://book.51cto.com/art/200908/142708.htm

9.3 ContentProvider

当数据需要在应用程序间共享时,我们就可以利用ContentProvider为数据定义一个URI。之后其他应用程序对数据进行查询或者修改时,只需要从当前上下文对象获得一个ContentResolver(内容解析器)传入相应的URI就可以了。本节中将以前面创建的code.db数据库为例,向读者介绍如何定义一个ContentProvider,以及如何在其他程序中使用ContentResolver访问URI所指定的数据。

9.3.1 定义ContentProvider(1)

要为当前应用程序的私有数据定义URI,就需要专门定义一个继承自ContentProvider的类,然后根据不同的操作调用的方法去实现这些方法的功能。下面我们用SQLite2这个例子,来为它的数据库code.db定义一个URI。

首先,在SQLite2的包中创建一个新类ContryCode.java,来装入所有与数据库操作有关的静态字段,以便于打包成JAR文件供其他应用程序调用。

Java代码 复制代码
  1. 1packagecom.studio.android.chp9.ex3;
  2. 2
  3. 3importandroid.net.Uri;
  4. 4
  5. 5publicclassCountryCode{
  6. 6
  7. 7publicstaticfinalStringDB_NAME="code.db";
  8. 8publicstaticfinalStringTB_NAME="countrycode";
  9. 9publicstaticfinalintVERSION=1;
  10. 10
  11. 11publicstaticfinalStringID="_id";
  12. 12publicstaticfinalStringCOUNTRY="country";
  13. 13publicstaticfinalStringCODE="code";
  14. 14
  15. 15publicstaticfinalStringAUTHORITY=
  16. 16"com.studio.andriod.provider.countrycode";
  17. 17publicstaticfinalintITEM=1;
  18. 18publicstaticfinalintITEM_ID=2;
  19. 19
  20. 20publicstaticfinalStringCONTENT_TYPE=
  21. 21"vnd.android.cursor.dir/vnd.studio.android.countrycode";
  22. 22publicstaticfinalStringCONTENT_ITEM_TYPE=
  23. 23"vnd.android.cursor.item/vnd.studio.android.countrycode";
  24. 24
  25. 25publicstaticfinalUriCONTENT_URI=
  26. 26Uri.parse("content://"+AUTHORITY+"/item");
  27. 27}

其中DB_NAME、TB_NAME和VERSION分别定义了数据库和表的名称以及数据库的版本号。ID、COUNTRY和CODE分别定义的是表中的各个列的列名。AUTHORITY定义了标识ContentProvider的字符串,ITEM和ITEM_ID分别用于UriMatcher(资源标识符匹配器)中对路径item和item/id的匹配号码。CONTENT_TYPE和CONTENT_ITEM_TYPE定义了数据的MIME类型。需要注意的是,单一数据的MIME类型字符串应该以vnd.android.cursor.item/开头,数据集的MIME类型字符串则应该以vnd.android.cursor.dir/开头。CONTENT_URI定义的是查询当前表数据的content://样式URI。

接下来,同样是在SQLite2的包中创建一个继承自ContentProvider的类MyProvider.java,来实现对数据操作的各个方法。这里将用到MyHelper来辅助获得SQLiteDatabase对象,虽然也可以直接使用Context.OpenOrCreate()方法获得,但不及使用数据库打开辅助类方便。

Java代码 复制代码
  1. publicclassMyProviderextendsContentProvider{
  2. MyHelperdbHelper;
  3. privatestaticfinalUriMatchersMatcher;
  4. static{
  5. sMatcher=newUriMatcher(UriMatcher.NO_MATCH);
  6. sMatcher.addURI(CountryCode.AUTHORITY,
  7. "item",CountryCode.ITEM);
  8. sMatcher.addURI(CountryCode.AUTHORITY,
  9. "item/#",CountryCode.ITEM_ID);
  10. }
  11. ...
  12. }

这里UriMatcher类型的静态字段是用来匹配传入到ContentProvider中的Uri的类。其构造方法传入的匹配码是使用match()方法匹配根路径时返回的值,这个匹配码可以为一个大于零的数表示匹配根路径或传入-1,即常量UriMatcher.NO_MATCH表示不匹配根路径。addURI()方法是用来增加其他URI匹配路径的,第一个参数传入标识ContentProvider的AUTHORITY字符串。第二个参数传入需要匹配的路径,这里的#代表匹配任意数字,另外还可以用*来匹配任意文本。第三个参数必须传入一个大于零的匹配码,用于match()方法对相匹配的URI返回相对应的匹配码。

ContentProvider里针对数据的各种操作定义了6个抽象方法,下面是对各个方法的实现和讲解。

Java代码 复制代码
  1. @Override
  2. publicbooleanonCreate(){
  3. dbHelper=newMyHelper(getContext(),CountryCode.DB_NAME,
  4. null,CountryCode.VERSION);
  5. returntrue;
  6. }

每当ContentProvider启动时都会回调onCreate()方法。此方法主要进行一些ContentProvider初始化的工作,返回true表示初始化成功,返回false则初始化失败。在这个ContentProvider中,主要是构造了需要操作数据库的辅助类对象。

Java代码 复制代码
  1. @Override
  2. publicStringgetType(Uriuri){
  3. switch(sMatcher.match(uri)){
  4. caseCountryCode.ITEM:
  5. returnCountryCode.CONTENT_TYPE;
  6. caseCountryCode.ITEM_ID:
  7. returnCountryCode.CONTENT_ITEM_TYPE;
  8. default:
  9. thrownewIllegalArgumentException("UnknownURI"+uri);
  10. }
  11. }


getTyper()是用来返回数据的MIME类型的方法。使用sMatcher对URI进行匹配,并返回相应的MIME类型字符串,若无法匹配传入的URI,抛出IllegalArgumentException异常。



Java代码 复制代码
  1. @Override
  2. publicintdelete(Uriuri,Stringwhere,String[]args){
  3. SQLiteDatabasedb=dbHelper.getWritableDatabase();
  4. intcount;
  5. switch(sMatcher.match(uri)){
  6. caseCountryCode.ITEM:
  7. count=db.delete(CountryCode.TB_NAME,where,args);
  8. break;
  9. caseCountryCode.ITEM_ID:
  10. Stringid=uri.getPathSegments().get(1);
  11. count=db.delete(CountryCode.TB_NAME,CountryCode.ID+"="+id
  12. +(!TextUtils.isEmpty(where)?"AND("+where+')':""),args);
  13. break;
  14. default:
  15. thrownewIllegalArgumentException("UnknownURI"+uri);
  16. }
  17. getContext().getContentResolver().notifyChange(uri,null);
  18. returncount;
  19. }
  20. @Override
  21. publicintupdate(Uriuri,ContentValuesvalues,
  22. Stringwhere,String[]args){
  23. SQLiteDatabasedb=dbHelper.getWritableDatabase();
  24. intcount;
  25. switch(sMatcher.match(uri)){
  26. caseCountryCode.ITEM:
  27. count=db.update(CountryCode.TB_NAME,values,where,args);
  28. break;
  29. caseCountryCode.ITEM_ID:
  30. Stringid=uri.getPathSegments().get(1);
  31. count=db.update(CountryCode.TB_NAME,values,CountryCode.ID+"="+id
  32. +(!TextUtils.isEmpty(where)?"AND("+where+')':""),args);
  33. break;
  34. default:
  35. thrownewIllegalArgumentException("UnknownURI"+uri);
  36. }
  37. getContext().getContentResolver().notifyChange(uri,null);
  38. returncount;
  39. }

delete()和update()方法分别用于数据的删除和修改操作,返回的是所影响数据的数目。我们这里两种方法的实现比较相似。首先利用数据库辅助对象获取一个SQLiteDatabase对象。然后根据传入的Uri用sMatcher进行匹配,对单个数据或数据集进行删除或修改,以便于在调用SQLiteDatabase对象的删除或修改方法时where语句中使用不同的表达式。这里通过调用getContext()方法获得调用update()方法的Context对象,再利用这个Context对象来获取一个ContentResolver的对象。notifyChange()方法则用来通知注册在此URI上的观察者(observer)数据发生了改变。最后返回删除或修改数据的行数。

Java代码 复制代码
  1. @Override
  2. publicUriinsert(Uriuri,ContentValuesinitialValues){
  3. SQLiteDatabasedb=dbHelper.getWritableDatabase();
  4. longrowId;
  5. if(sMatcher.match(uri)!=CountryCode.ITEM){
  6. thrownewIllegalArgumentException("UnknownURI"+uri);
  7. }
  8. rowId=
  9. db.insert(CountryCode.TB_NAME,CountryCode.ID,initialValues);
  10. if(rowId>0){
  11. UrinoteUri=
  12. ContentUris.withAppendedId(CountryCode.CONTENT_URI,rowId);
  13. getContext().getContentResolver().notifyChange(noteUri,null);
  14. returnnoteUri;
  15. }
  16. thrownewSQLException("Failedtoinsertrowinto"+uri);
  17. }

insert()方法用来插入数据,最后返回新插入数据的URI。在此方法的实现中,只接受数据集的URI,即指向表的URI。然后利用数据库辅助对象获得的SQLiteDatabase对象,调用insert()方法向指定表中插入数据。最后通知观察者数据发生变化,返回插入数据的URI。

Java代码 复制代码
  1. @Override
  2. publicCursorquery(Uriuri,String[]projection,
  3. Stringselection,String[]args,Stringorder){
  4. SQLiteDatabasedb=dbHelper.getReadableDatabase();
  5. Cursorc;
  6. switch(sMatcher.match(uri)){
  7. caseCountryCode.ITEM:
  8. c=db.query(CountryCode.TB_NAME,projection,selection,
  9. args,null,null,order);
  10. break;
  11. caseCountryCode.ITEM_ID:
  12. Stringid=uri.getPathSegments().get(1);
  13. c=db.query(CountryCode.TB_NAME,projection,CountryCode.ID+"="
  14. +id
  15. +(!TextUtils.isEmpty(selection)
  16. ?"AND("+selection+')':""),
  17. args,null,null,order);
  18. break;
  19. default:
  20. thrownewIllegalArgumentException("UnknownURI"+uri);
  21. }
  22. c.setNotificationUri(getContext().getContentResolver(),uri);
  23. returnc;
  24. }

query()是对数据进行查询的方法,最终将查询的结果包装入一个Cursor对象并返回。其实现首先还是通过数据库辅助对象获取一个SQLiteDatabase对象,然后使用sMatcher对传入URI进行匹配,并分别对单数据和多数据的URI构造不同的where语句表达式并查询。setNotificationUri()方法是用来为Cursor对象注册一个观察数据变化的URI。

实现完这几个抽象方法后,一个完整的ContentProvider就被定义好了,剩下的就是在Android-Manifest.xml中对这个ContentProvider的声明了。在AndroidManifest.xml中添加如下声明代码。

<provider android:name="MyProvider"
android:authorities="com.studio.andriod.provider.countrycode"/>
其中android:name需要设置成刚才定义ContentProvider类的类名,android:authorities则指定了在content://样式的URI中标识这个ContentProvider的字符串。另外,可以设置android:readPermission和android:writePermission这两个属性, 来分别指定对这个ContentProvider中数据读和写操作的权限。也可以在onCreate()方法的实现中调用setRead-Permission()和setWritePermission()方法来动态指定权限。

为了让其他程序更加方便地使用我们自己定义的ContentProvider,一般会将要用到的静态数据导出成JAR归档文件。如本程序中将所有要用到的静态字段都放在了类CountryCode中。下面是将其打包成JAR文件的步骤。

(1) 在项目文件夹上或CountryCode.java文件上右键,选择Export...。


(2) 在弹出的选择导出类型的对话框中,点击选择JAR file,然后点Next。

(3) 在选择要导出的文件框中,只选择CountryCode.java。找到Browse...按钮指定导出路径(默认为workspace),点选Finish完成导出CountryCode.jar。

导出了JAR文件后,若需要在其他应用程序中使用,只需要为该项目添加外部的归档文件即可。在该项目文件夹上右键找到Build path→Add External Archive,如图9-5所示,然后选择要添加的JAR文件就可以在程序中使用import语句导入归档文件中的内容了。

转自http://blog.chinaunix.net/u3/90973/showart_2161195.html
ContentProvider是什么时候创建的,是谁创建的?访问某个应用程序共享的数据,是否需要启动这个应用程序?这个问题在 Android SDK中没有明确说明,但是从数据共享的角度出发,ContentProvider应该是Android在系统启动时就创建了,否则就谈不上数据共享了。 这就要求在AndroidManifest.XML中使用元素明确定义。
可能会有多个程序同时通过ContentResolver访问一个ContentProvider,会不会导致像数据库那样的“脏数 据”?这个问题一方面需要数据库访问的同步,尤其是数据写入的同步,在AndroidManifest.XML中定义ContentProvider的时 候,需要考虑是元素multiprocess属性的值;另外一方面Android在ContentResolver中提供了notifyChange() 接口,在数据改变时会通知其他ContentObserver,这个地方应该使用了观察者模式,在ContentResolver中应该有一些类似 register,unregister的接口。
至此,已经对ContentProvider提供了比较全面的分析,至于如何创建ContentProvider,可通过2种方法:创建一个属于你自己的 ContentProvider或者将你的数据添加到一个已经存在的ContentProvider中,当然前提是有相同数据类型并且有写入 Content provider的权限。在Android SDK的sample中提供的
分享到:
评论

相关推荐

    contentProvider监听的例子

    一个自定义的ContentProvider需要继承自`android.content.ContentProvider`类,并实现其核心方法,如`onCreate()`、`query()`、`insert()`、`update()`、`delete()`等。`onCreate()`方法在ContentProvider启动时被...

    android-关于ContentProvider的使用例子

    - `Uri`(统一资源标识符)是ContentProvider的核心,它唯一标识了ContentProvider中的一个或一组数据项。通常, Uri由两部分组成:authority(权限)和path(路径)。 - `MIME类型`用于描述数据的类型,如文本、...

    自定义ContentProvider的简单例子

    首先,创建一个ContentProvider需要继承`android.content.ContentProvider`类,并重写其中的关键方法: 1. `onCreate()`: 当ContentProvider被系统加载时调用。在这里可以进行初始化操作,如数据库的创建和打开。 ...

    android对sqlite、contentprovider的例子

    SQLite是一个轻量级的数据库系统,适用于移动设备,而ContentProvider则是一种接口,允许不同应用程序之间共享数据。让我们深入探讨这两个概念以及如何在实际项目中使用它们。 **SQLite** SQLite 是一个嵌入式 SQL...

    ContentProvider完整例子

    4. 数据库操作:如果ContentProvider是基于SQLite数据库,你需要创建一个SQLiteOpenHelper子类,用于数据库的创建和版本管理,同时提供对数据库操作的方法。 5. 实现数据操作逻辑:在ContentProvider的上述方法中...

    contentProvider,sqlit例子

    ContentProvider作为Android系统中数据共享的桥梁,SQLite则是一个轻量级的嵌入式数据库,适用于移动设备。在这个综合例子中,我们将深入探讨如何利用它们进行数据的存取和管理。 首先,ContentProvider是Android...

    ContentProvider 例子

    一个ContentProvider由以下几个关键部分组成: 1. **Provider类**:继承自`android.content.ContentProvider`,并覆盖其生命周期方法,如`onCreate()`、`query()`、`insert()`、`update()`、`delete()`和`getType()...

    android contentprovider的例子

    在Android应用开发中,ContentProvider是一个至关重要的组件,它扮演着数据共享的角色,使得不同的应用程序之间可以安全地读写共享数据。"android contentprovider的例子"这个主题将带你深入理解ContentProvider的...

    ContentProvider操作数据库小例子

    一个ContentProvider类需要继承自`android.content.ContentProvider`,并实现其关键方法,如`onCreate()`、`query()`、`insert()`、`update()`和`delete()`。这些方法分别对应于对数据进行创建、查询、更新和删除的...

    Android+Room+ContentProvider

    在这个例子中,我们创建了一个简单的ContentProvider,它将Room数据库的数据暴露给其他应用。其他应用可以通过ContentResolver访问这些数据,使用标准的URI和ContentProvider操作。 综上所述,Android Room简化了...

    android contentprovider使用示例

    假设我们有一个名为"Contacts"的数据表,包含id, name和phone字段,我们可以这样创建一个简单的ContentProvider: ```java public class MyContactProvider extends ContentProvider { private static final ...

    ContentProvider使用方法demo

    - `ContentProviderDemo`:可能包含一个ContentProvider处理多张数据库表的例子,展示如何通过Uri匹配和封装方法来区分不同的数据操作。 总之,ContentProvider是Android系统中数据共享的重要机制,通过合理设计和...

    contentprovider参考例子

    ContentProvider会与一个SQLite数据库交互,创建一个名为“Student”的表,并提供相应的数据操作接口。 例如,`query()`方法可能如下: ```java @Override public Cursor query(Uri uri, String[] projection, ...

    contentProvider Demo实例

    在这个例子中,开发者可能会创建一个简单的SQLite数据库表,然后在ContentProvider中处理与这个表相关的操作。 此外,为了让其他应用能够找到并使用这个ContentProvider,还需要在AndroidManifest.xml文件中注册...

    ContentProvider实现数据库操作

    ContentProvider是一个抽象类,需要我们继承并实现其关键方法,如query(), insert(), update(), delete()以及getType()等。这些方法分别对应于对数据进行查询、插入、更新和删除的操作,以及获取特定Uri类型的功能。...

    ContentProvider 翻译

    了解了基本原理后,我们可以通过一个简单的例子来实践创建ContentProvider。假设我们要创建一个存储学生信息的ContentProvider,首先定义Uri,如`content://com.example.provider/students`,然后创建名为`...

    contentprovider例子

    "contentprovider例子"这个主题聚焦于如何创建和使用Content Provider来实现在两个不同应用之间的数据交互。下面将详细阐述Content Provider的基本概念、结构、创建过程以及如何在两个APP间进行数据通信。 1. **...

    ContentProvider使用案例

    1. **定义Uri(统一资源标识符)**:每个ContentProvider都与一个或多个Uri关联,这些Uri用来唯一标识ContentProvider中的数据。例如,`content://com.example.provider/users` 就是一个典型的Uri,用于访问名为...

    ContentProvider的例子

    这是一个contentprovider的例子,里面包含了对数据库的操作,还有listview的应用和自定义的dialog应用,可是在后期中由于着重是测试provider,所以可能对那两个应用的少量代码删了一点,可是很好理解一看就明白,...

    使用contentprovider共享生词本数据

    在这个例子中,我们创建了一个新的ContentValues对象,填入了生词和定义,然后通过ContentResolver的`insert()`方法将其插入到ContentProvider中。 总结来说,通过创建一个自定义的ContentProvider并正确配置,可以...

Global site tag (gtag.js) - Google Analytics