Android中ContentProvider组件详解

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介:

一.Android四大组件

Android四大组件是Activity, Service, Content Provider,Broadcast Receiver

Activity作为程序界面,直接与用户交互

Service运行在后台,没有界面,完成特定的功能

ContentProvider维护应用数据,方便应用本身或其它应用访问

Broadcast Receiver提供异步广播消息接收机制,便于各应用/组件进行交互

二.什么是ContentProvider

        ContentProvider(内容提供者)是Android中的四大组件之一。主要用于对外共享数据,也就是通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider对指定应用中的数据进行操作。ContentProvider分为系统的和自定义的,系统的也就是例如联系人,图片等数据。

1.ContentProvider
        Android提供了一些主要数据类型的ContentProvider,比如音频、视频、图片和私人通讯录等。可在android.provider包下面找到一些Android提供的ContentProvider。通过获得这些ContentProvider可以查询它们包含的数据,当然前提是已获得适当的读取权限。
主要方法:

[java]  view plain  copy
 print ?
  1. <span style="font-size:12px;">public boolean onCreate() 在创建ContentProvider时调用  
  2. public Cursor query(Uri, String[], String, String[], String) 用于查询指定Uri的ContentProvider,返回一个Cursor  
  3. public Uri insert(Uri, ContentValues) 用于添加数据到指定Uri的ContentProvider中  
  4. public int update(Uri, ContentValues, String, String[]) 用于更新指定Uri的ContentProvider中的数据  
  5. public int delete(Uri, String, String[]) 用于从指定Uri的ContentProvider中删除数据  
  6. public String getType(Uri) 用于返回指定的Uri中的数据的MIME类型  
  7. *如果操作的数据属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/开头。  
  8. 例如:要得到所有person记录的Uri为content://contacts/person,那么返回的MIME类型字符串为"vnd.android.cursor.dir/person"。  
  9. *如果要操作的数据属于非集合类型数据,那么MIME类型字符串应该以vnd.android.cursor.item/开头。  
  10. 例如:要得到id为10的person记录的Uri为content://contacts/person/10,那么返回的MIME类型字符串应为"vnd.android.cursor.item/person"。</span>  

2.ContentResolver
        当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver类来完成,要获取ContentResolver对象,可以使用Context提供的getContentResolver()方法。

[java]  view plain  copy
 print ?
  1. <span style="font-size:12px;">ContentResolver cr = getContentResolver();</span>    

ContentResolver提供的方法和ContentProvider提供的方法对应的有以下几个方法。

[java]  view plain  copy
 print ?
  1. <span style="font-size:12px;">public Uri insert(Uri uri, ContentValues values) 用于添加数据到指定Uri的ContentProvider中。  
  2. public int delete(Uri uri, String selection, String[] selectionArgs) 用于从指定Uri的ContentProvider中删除数据。  
  3. public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 用于更新指定Uri的ContentProvider中的数据。  
  4. public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 用于查</span>询指定Uri的ContentProvider。  


3.Uri

        Uri 代表了要操作的数据,Uri 主要包含了两部分信息:1、需要操作的
ContentProvider;2、对ContentProvider中的什么数据进行操作。一个Uri由以
下几部分组成: 

       ContentProvider的scheme已经由Android所规定,scheme为content://。 
主机名(authorities)用于唯一标识这个ContentProvider,外部调用者可以根据
它找到对应的内容提供者(ContentProvider)。 
路径(Path)可以用来表示我们要操作的数据,路径的构建应该根据业务而定,
如下: 
要操作Person表中ID 为10的记录,可以构建这样的路径:/person/id/10,也
可以为/prson/10,构建什么样的路径需要与UriMatcher中注册的匹配Uri相一
致。例如:/person/id/10,那么匹配Uri需要也需要带id 为/preson/id/#,否则
可以写成/person/10. 
要操作person表中的所有记录,可以这样构建路径:/person 
如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法。如下: 
Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person") 

三、UriMatcher类使用介绍

        因为Uri代表了要操作的数据,所以我们经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher和ContentUris 。掌握它们的使用,会便于我们的开发工作。
UriMatcher类用于匹配Uri,它的用法如下:
首先第一步把你需要匹配Uri路径全部给注册上,如下:

[java]  view plain  copy
 print ?
  1. <span style="font-size:12px;color:#000000;">//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码     
  2. UriMatcher  sMatcher = new UriMatcher(UriMatcher.NO_MATCH);     
  3. //如果match()方法匹配content:    
  4. //com.ljq.provider.personprovider/person路径,返回匹配码为1,匹配Uri注册如下:     
  5. sMatcher.addURI("com.ljq.provider.personprovider", person", 1);    
  6. //添加需要匹配uri,如果匹配就会返回匹配码     
  7. //如果match()方法匹配content://com.ljq.provider.personprovider/person/230路径,返回匹配码为2,配Uri注册如下:     
  8. sMatcher.addURI("com.ljq.provider.personprovider""person/#"2);    
  9. //#号为通配符     
  10. //传入Uri,进行匹配     
  11. switch (sMatcher.match(Uri.parse("content://com.ljq.provider.personprovider/person/10"))) {      
  12.      case 1     
  13.        break;     
  14.      case 2     
  15.        break;     
  16.      default://不匹配     
  17.        break;     
  18.  }   </span>  

注册完需要匹配的Uri后,就可以使用sMatcher.match(uri)对输入的uri进
匹配,如果匹配正确就返回匹配码,匹配码是addUri()方法传入的第三个
数,假设匹配content://com.ljq.provider.personprovider/person 路径,返回
匹配码为1。

四、ContentUris介绍

ContentUris用于操作Uri后面的ID 部分,它有两个实用的方法: 
WithAppendedId(uri, id)用于为uri路径加上id 部分,如下:

[java]  view plain  copy
 print ?
  1. <span style="font-size:12px;color:#000000;">Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person")     
  2. Uri resultUri = ContentUris.withAppendedId(uri, 10);      
  3. //生成后的Uri为:content://com.ljq.provider.personprovider/person/10     
  4. parseId(uri)用于从路径中获取Id,如下:     
  5. Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person/10")     
  6. long personid = ContentUris.parseId(uri);    
  7. //获取的结果为:10</span>  

五、监听ContentProvider中数据的变化

        如果ContentProvider的访问者需要知道ContentProvider中数据发生变化,可以在ContentProvider中数据发生变化时调用getContentResovler().notifyChange(uri, null)来通知注册在此uri上的访问者,如下:

[java]  view plain  copy
 print ?
  1. <span style="font-size:12px;color:#000000;">public class PersonContentProvider extends ContentProvider {     
  2.      public Uri insert(Uri uri, ContentValues values) {     
  3.         db.insert("person""personid", values);     
  4.         getContext().getContentResolver().notifyChange(uri, null);     
  5.      }     
  6.  }   </span>  

        如果ContentProvider 的访问者需要得到数据变化通知,必须使用ContentObserver对数据(数据采用Uri描述)进行监听,当监听到数据变化通知时,系统就会调用ContentObserver的onChange()方法,如下:

[java]  view plain  copy
 print ?
  1. <span style="font-size:12px;color:#000000;">getContentResolver().registerContentObserver(Uri.parse("content://com.ljq.providers.personprovider/person"),     
  2.        truenew PersonObserver(new Handler()));     
  3. public class PersonObserver extends ContentObserver{     
  4.    public PersonObserver(Handler handler) {     
  5.       super(handler);     
  6.    }     
  7.    public void onChange(boolean selfChange) {     
  8.       //此处可以进行相应的业务处理     
  9.    }     
  10. }   </span>  


六、具体实例

[java]  view plain  copy
 print ?
  1. <span style="font-size:12px;color:#000000;">public class FirstContentProvider extends ContentProvider {    
  2.         
  3.         // UriMatcher类主要用来匹配Uri    
  4.         private static final UriMatcher uriMatcher = new UriMatcher(    
  5.                 UriMatcher.NO_MATCH);    
  6.         private MySqlite mysqlite;    
  7.         static {    
  8.             // 注册向外部程序提供的Uri    
  9.             uriMatcher.addURI(UserInfo.AUTOR, "userinfo"1);    
  10.             uriMatcher.addURI(UserInfo.AUTOR, "userinfoall"2);    
  11.         }    
  12.         //删除数据    
  13.         @Override    
  14.         public int delete(Uri uri, String selection, String[] selectionArgs) {    
  15.             int number = 0;    
  16.             if (uriMatcher.match(uri) == 1) {    
  17.                 // 根据条件删除数据,并获取删除的行数    
  18.                 number = mysqlite.getReadableDatabase().delete("user_info",    
  19.                         selection, selectionArgs);    
  20.             }    
  21.             // 通知数据已经改变    
  22.             getContext().getContentResolver().notifyChange(uri, null);    
  23.             return number;    
  24.         }    
  25.         
  26.         @Override    
  27.         public String getType(Uri uri) {    
  28.         
  29.             return null;    
  30.         }    
  31.         //插入数据    
  32.         @Override    
  33.         public Uri insert(Uri uri, ContentValues values) {    
  34.             String name = values.getAsString(UserInfo.User.NAME).toString();    
  35.             String age = values.getAsInteger(UserInfo.User.AGE).toString();    
  36.             String maxId = "select max(id) id from user_info";    
  37.             Cursor cursor = mysqlite.getReadableDatabase().rawQuery(maxId, null);    
  38.             cursor.moveToFirst();    
  39.             int userid = cursor.getInt(0) + 1;    
  40.             if (uriMatcher.match(uri) == 1) {    
  41.         
  42.                 mysqlite.getWritableDatabase().execSQL(    
  43.                         "insert into user_info values(?,?,?)",    
  44.                         new String[] { String.valueOf(userid), name, age });    
  45.             }    
  46.             return uri;    
  47.         }    
  48.         
  49.         // 连接数据库    
  50.         @Override    
  51.         public boolean onCreate() {    
  52.             mysqlite = new MySqlite(getContext(), "userinfo.db"null1);    
  53.             return true;    
  54.         }    
  55.         //查询数据    
  56.         @Override    
  57.         public Cursor query(Uri uri, String[] projection, String selection,    
  58.                 String[] selectionArgs, String sortOrder) {    
  59.             SQLiteDatabase sqlite = mysqlite.getReadableDatabase();    
  60.             String str = "select name,age from user_info";    
  61.             if (uriMatcher.match(uri) == 1) {    
  62.                 str += " where " + selection;    
  63.             }    
  64.             Cursor cursor = sqlite.rawQuery(str, selectionArgs);    
  65.             return cursor;    
  66.         }    
  67.         //修改数据    
  68.         @Override    
  69.         public int update(Uri uri, ContentValues values, String selection,    
  70.                 String[] selectionArgs) {    
  71.             SQLiteDatabase sqlite = mysqlite.getReadableDatabase();    
  72.             int number = 0;    
  73.             if (uriMatcher.match(uri) == 1) {    
  74.                 number = sqlite.update("user_info", values, selection,    
  75.                         selectionArgs);    
  76.             }    
  77.             return number;    
  78.         }    
  79.         
  80.     }  </span>  




转载:http://blog.csdn.net/chaoyu168/article/details/50394137

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
10月前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
11月前
|
存储 Android开发 开发者
深入理解安卓应用开发的核心组件
【10月更文挑战第8天】探索Android应用开发的精髓,本文带你了解安卓核心组件的奥秘,包括Activity、Service、BroadcastReceiver和ContentProvider。我们将通过代码示例,揭示这些组件如何协同工作,构建出功能强大且响应迅速的应用程序。无论你是初学者还是资深开发者,这篇文章都将为你提供新的视角和深度知识。
|
11月前
|
数据可视化 Android开发 开发者
安卓应用开发中的自定义View组件
【10月更文挑战第5天】在安卓应用开发中,自定义View组件是提升用户交互体验的利器。本篇将深入探讨如何从零开始创建自定义View,包括设计理念、实现步骤以及性能优化技巧,帮助开发者打造流畅且富有创意的用户界面。
301 0
|
9月前
|
XML 搜索推荐 前端开发
安卓开发中的自定义视图:打造个性化UI组件
在安卓应用开发中,自定义视图是一种强大的工具,它允许开发者创造独一无二的用户界面元素,从而提升应用的外观和用户体验。本文将通过一个简单的自定义视图示例,引导你了解如何在安卓项目中实现自定义组件,并探讨其背后的技术原理。我们将从基础的View类讲起,逐步深入到绘图、事件处理以及性能优化等方面。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和技巧。
|
11月前
|
XML 前端开发 Java
安卓应用开发中的自定义View组件
【10月更文挑战第5天】自定义View是安卓应用开发的一块基石,它为开发者提供了无限的可能。通过掌握其原理和实现方法,可以创造出既美观又实用的用户界面。本文将引导你了解自定义View的创建过程,包括绘制技巧、事件处理以及性能优化等关键步骤。
|
11月前
|
测试技术 数据库 Android开发
深入解析Android架构组件——Jetpack的使用与实践
本文旨在探讨谷歌推出的Android架构组件——Jetpack,在现代Android开发中的应用。Jetpack作为一系列库和工具的集合,旨在帮助开发者更轻松地编写出健壮、可维护且性能优异的应用。通过详细解析各个组件如Lifecycle、ViewModel、LiveData等,我们将了解其原理和使用场景,并结合实例展示如何在实际项目中应用这些组件,提升开发效率和应用质量。
308 6
|
12月前
|
存储 开发框架 数据可视化
深入解析Android应用开发中的四大核心组件
本文将探讨Android开发中的四大核心组件——Activity、Service、BroadcastReceiver和ContentProvider。我们将深入了解每个组件的定义、作用、使用方法及它们之间的交互方式,以帮助开发者更好地理解和应用这些组件,提升Android应用开发的能力和效率。
848 5
|
缓存 搜索推荐 Android开发
安卓应用开发中的自定义View组件实践
【9月更文挑战第10天】在安卓开发领域,自定义View是提升用户体验和实现界面个性化的重要手段。本文将通过一个实际案例,展示如何在安卓项目中创建和使用自定义View组件,包括设计思路、实现步骤以及可能遇到的问题和解决方案。文章不仅提供了代码示例,还深入探讨了自定义View的性能优化技巧,旨在帮助开发者更好地掌握这一技能。
|
存储 搜索推荐 Java
探索安卓开发中的自定义视图:打造个性化UI组件Java中的异常处理:从基础到高级
【8月更文挑战第29天】在安卓应用的海洋中,一个独特的用户界面(UI)能让应用脱颖而出。自定义视图是实现这一目标的强大工具。本文将通过一个简单的自定义计数器视图示例,展示如何从零开始创建一个具有独特风格和功能的安卓UI组件,并讨论在此过程中涉及的设计原则、性能优化和兼容性问题。准备好让你的应用与众不同了吗?让我们开始吧!
|
XML 搜索推荐 Android开发
安卓开发中的自定义View组件实践
【8月更文挑战第30天】探索Android世界,自定义View是提升应用界面的关键。本文以简洁的语言带你了解如何创建自定义View,从基础到高级技巧,一步步打造个性化的UI组件。

热门文章

最新文章