Android中ContentProvider组件详解

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 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可以查询它们包含的数据,当然前提是已获得适当的读取权限。
主要方法:

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

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

<span style="font-size:12px;">ContentResolver cr = getContentResolver();</span>  
ContentResolver提供的方法和ContentProvider提供的方法对应的有以下几个方法。

<span style="font-size:12px;">public Uri insert(Uri uri, ContentValues values) 用于添加数据到指定Uri的ContentProvider中。
public int delete(Uri uri, String selection, String[] selectionArgs) 用于从指定Uri的ContentProvider中删除数据。
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 用于更新指定Uri的ContentProvider中的数据。
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路径全部给注册上,如下:

<span style="font-size:12px;color:#000000;">//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码   
UriMatcher  sMatcher = new UriMatcher(UriMatcher.NO_MATCH);   
//如果match()方法匹配content:  
//com.ljq.provider.personprovider/person路径,返回匹配码为1,匹配Uri注册如下:   
sMatcher.addURI("com.ljq.provider.personprovider", person", 1);  
//添加需要匹配uri,如果匹配就会返回匹配码   
//如果match()方法匹配content://com.ljq.provider.personprovider/person/230路径,返回匹配码为2,配Uri注册如下:   
sMatcher.addURI("com.ljq.provider.personprovider", "person/#", 2);  
//#号为通配符   
//传入Uri,进行匹配   
switch (sMatcher.match(Uri.parse("content://com.ljq.provider.personprovider/person/10"))) {    
     case 1   
       break;   
     case 2   
       break;   
     default://不匹配   
       break;   
 }   </span>
注册完需要匹配的Uri后,就可以使用sMatcher.match(uri)对输入的uri进
匹配,如果匹配正确就返回匹配码,匹配码是addUri()方法传入的第三个
数,假设匹配content://com.ljq.provider.personprovider/person 路径,返回
匹配码为1。

四、ContentUris介绍

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

<span style="font-size:12px;color:#000000;">Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person")   
Uri resultUri = ContentUris.withAppendedId(uri, 10);    
//生成后的Uri为:content://com.ljq.provider.personprovider/person/10   
parseId(uri)用于从路径中获取Id,如下:   
Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person/10")   
long personid = ContentUris.parseId(uri);  
//获取的结果为:10</span>

五、监听ContentProvider中数据的变化

        如果ContentProvider的访问者需要知道ContentProvider中数据发生变化,可以在ContentProvider中数据发生变化时调用getContentResovler().notifyChange(uri, null)来通知注册在此uri上的访问者,如下:
<span style="font-size:12px;color:#000000;">public class PersonContentProvider extends ContentProvider {   
     public Uri insert(Uri uri, ContentValues values) {   
        db.insert("person", "personid", values);   
        getContext().getContentResolver().notifyChange(uri, null);   
     }   
 }   </span>
        如果ContentProvider 的访问者需要得到数据变化通知,必须使用ContentObserver对数据(数据采用Uri描述)进行监听,当监听到数据变化通知时,系统就会调用ContentObserver的onChange()方法,如下:
<span style="font-size:12px;color:#000000;">getContentResolver().registerContentObserver(Uri.parse("content://com.ljq.providers.personprovider/person"),   
       true, new PersonObserver(new Handler()));   
public class PersonObserver extends ContentObserver{   
   public PersonObserver(Handler handler) {   
      super(handler);   
   }   
   public void onChange(boolean selfChange) {   
      //此处可以进行相应的业务处理   
   }   
}   </span>

六、具体实例
<span style="font-size:12px;color:#000000;">public class FirstContentProvider extends ContentProvider {  
      
        // UriMatcher类主要用来匹配Uri  
        private static final UriMatcher uriMatcher = new UriMatcher(  
                UriMatcher.NO_MATCH);  
        private MySqlite mysqlite;  
        static {  
            // 注册向外部程序提供的Uri  
            uriMatcher.addURI(UserInfo.AUTOR, "userinfo", 1);  
            uriMatcher.addURI(UserInfo.AUTOR, "userinfoall", 2);  
        }  
        //删除数据  
        @Override  
        public int delete(Uri uri, String selection, String[] selectionArgs) {  
            int number = 0;  
            if (uriMatcher.match(uri) == 1) {  
                // 根据条件删除数据,并获取删除的行数  
                number = mysqlite.getReadableDatabase().delete("user_info",  
                        selection, selectionArgs);  
            }  
            // 通知数据已经改变  
            getContext().getContentResolver().notifyChange(uri, null);  
            return number;  
        }  
      
        @Override  
        public String getType(Uri uri) {  
      
            return null;  
        }  
        //插入数据  
        @Override  
        public Uri insert(Uri uri, ContentValues values) {  
            String name = values.getAsString(UserInfo.User.NAME).toString();  
            String age = values.getAsInteger(UserInfo.User.AGE).toString();  
            String maxId = "select max(id) id from user_info";  
            Cursor cursor = mysqlite.getReadableDatabase().rawQuery(maxId, null);  
            cursor.moveToFirst();  
            int userid = cursor.getInt(0) + 1;  
            if (uriMatcher.match(uri) == 1) {  
      
                mysqlite.getWritableDatabase().execSQL(  
                        "insert into user_info values(?,?,?)",  
                        new String[] { String.valueOf(userid), name, age });  
            }  
            return uri;  
        }  
      
        // 连接数据库  
        @Override  
        public boolean onCreate() {  
            mysqlite = new MySqlite(getContext(), "userinfo.db", null, 1);  
            return true;  
        }  
        //查询数据  
        @Override  
        public Cursor query(Uri uri, String[] projection, String selection,  
                String[] selectionArgs, String sortOrder) {  
            SQLiteDatabase sqlite = mysqlite.getReadableDatabase();  
            String str = "select name,age from user_info";  
            if (uriMatcher.match(uri) == 1) {  
                str += " where " + selection;  
            }  
            Cursor cursor = sqlite.rawQuery(str, selectionArgs);  
            return cursor;  
        }  
        //修改数据  
        @Override  
        public int update(Uri uri, ContentValues values, String selection,  
                String[] selectionArgs) {  
            SQLiteDatabase sqlite = mysqlite.getReadableDatabase();  
            int number = 0;  
            if (uriMatcher.match(uri) == 1) {  
                number = sqlite.update("user_info", values, selection,  
                        selectionArgs);  
            }  
            return number;  
        }  
      
    }  </span>


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
API 数据库 Android开发
Android ContentProvider内容提供者详解
Android ContentProvider内容提供者详解
78 2
|
Android开发
Android:四大组件之 Activity
Activity 是一个用户界面,通过加载一个指定的布局文件来展示各种 UI 元素,同时处理这些 UI 元素的交互事件,如点击、输入文本等。不同的 Activity 之间可以进行跳转,将不同的页面串联起来,共同完成特定的操作流程。每个应用都是由一个或者多个 Activity 组成。
109 0
Android:四大组件之 Activity
|
Java 开发工具 Android开发
Android中的四大组件
Android中的四大组件
|
XML 存储 Java
【Android】Android对于Activity的运用以及ViewGroup和 用户界面组件在项目中的运用
【Android】Android对于Activity的运用以及ViewGroup和 用户界面组件在项目中的运用
154 0
【Android】Android对于Activity的运用以及ViewGroup和 用户界面组件在项目中的运用
|
存储 数据可视化 Android开发
Android的四大组件之Activity
Activity( 活动 ) 一.创建Activity 二.启动Activity的两种方式 三.Activity之间页面跳转 四.Activity之间的数据传输 五.实现上一个activity接收下一个activity关闭之后传递的数据
120 0
|
Web App开发 数据库 Android开发
|
存储 Android开发 数据库管理
|
数据库 Android开发 数据安全/隐私保护