ContentProvider学习笔记

1、 ContentProvider基本概念

ContentProvider向我们提供了我们在应用程序之间共享数据的一种机制,虽然采用文件和SharedPreferences都可以实现应用程序间的数据共享,但是这样数据访问方式会因数据存储方式不同而不一样,如采用文件方式对外共享数据,需要对文件进行读写操作,采用SharedPreferences共享数据,需要使用SharedPreferences的API进行数据的读写,而使用ContentProvider则达到了不同应用程序间数据访问方式的统一。

(1)     ContentProvider提供为存储和获取数据提供统一的接口。

(2)     使用ContentProvider可以在不同的应用程序直接共享数据。

(3)     Android为常见的一些数据提供了ContentProvider(包括音频、视频、图片和通讯录等)。

    ContentProvider使用表的形式来组织数据

2、 URI[统一资源标识符]

(1)     每一个ContentProvider都拥有一个公共的URI,这个URI用于标识这个

ContentProvider所提供的数据。

(2)     Android所提供的ContentProvider都存放在android.provider包当中。

(3)     命名规范:Uri主要包含了两部分信息:1》需要操作的ContentProvider ,2》对ContentProvider中的什么数据进行操作,一个Uri由以下几部分组成:

  ContentProvider(内容提供者)的scheme已经由Android所规定, scheme为:content://
  主机名(或叫Authority)用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。
  路径(path)可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
  要操作person表中id为10的记录,可以构建这样的路径:/person/10
  要操作person表中id为10的记录的name字段, person/10/name
  要操作person表中的所有记录,可以构建这样的路径:/person
  要操作xxx表中的记录,可以构建这样的路径:/xxx
  当然要操作的数据不一定来自数据库,也可以是文件、xml或网络等其他存储方式,如下:
  要操作xml文件中person节点下的name节点,可以构建这样的路径:/person/name
  如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
  Uri uri =
Uri.parse("content://com.ljq.provider.personprovider/person")

3、 ContentProvider的实现方法

(1)    
query():查询

(2)    
insert():插入

(3)    
update():更新

(4)    
delete():删除

(5)    
getType():得到数据类型

(6)    
onCreate():创建时的回调函数

4、 实现一个ContentProvider的步骤:

(1)     定义一个类,继承ContentProvider

(2)     定义一个CONTENT_URI常量,并添加供外界访问的接口

(3)     编写代码实现ContentProvider的insert(),delete(),update(),query()等方法

(4)     在AndroidManifest.xml文件中配置此ContentProvider

5、 实例,编写StudentProvider

(1)编写自己的StudentProvider类继承ContentProvider

package com.demo.sqlite.provider;

import com.demo.sqlite.dao.DBOpenHelper;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.text.TextUtils; /**
* 自定义一个学生的内容提供者
*
* @author yinbenyang
*
*/
public class StudentProvider extends ContentProvider { private DBOpenHelper helper;
private static final int NUM1 = 1;
private static final int NUM2 = 2;
SQLiteDatabase db = null;
private static final String AUTHORITY = "come.demo.sqlite.studentprovider";
// 常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
private static final UriMatcher matcher = new UriMatcher(
UriMatcher.NO_MATCH);
// 添加两个供外界使用的接口
static {
// 如果match()方法匹配content://come.demo.sqlite.studentprovider/t_student路径,返回匹配码为1
matcher.addURI(AUTHORITY, "t_student", NUM1);
// 如果match()方法匹配content://come.demo.sqlite.studentprovider/t_student/1路径,返回匹配码为2
matcher.addURI(AUTHORITY, "t_student/#", NUM2); // #代表通配符
} @Override
public boolean onCreate() {
helper = new DBOpenHelper(this.getContext());
db = helper.getWritableDatabase();
return true;
} // 查询操作
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
Cursor cursor = null; // 用于储存一个查询的 结果
switch (matcher.match(uri)) {
// content://come.demo.sqlite.studentprovider/t_student
case NUM1:
cursor = db.query("t_student", projection, selection,
selectionArgs, null, null, sortOrder);
break;
// content://come.demo.sqlite.studentprovider/t_student/#
case NUM2:
long sid = ContentUris.parseId(uri); // 从uri中获取id的值
String where = TextUtils.isEmpty(selection) ? "sid = ?" : selection
+ "sid = ?";
String params[] = new String[] { String.valueOf(sid) };
if (!TextUtils.isEmpty(selection) && selectionArgs != null) {
params = new String[selectionArgs.length + 1];
for (int i = 0; i < selectionArgs.length; i++) {
params[i] = selectionArgs[i];
}
params[selectionArgs.length + 1] = String.valueOf(sid);
}
cursor = db.query("t_student", projection, where, params, null,
null, sortOrder);
break;
default:
throw new IllegalArgumentException("Unknown URL " + uri);
}
return cursor;
} // 返回当前Url所代表数据的MIME类型
@Override
public String getType(Uri uri) {
switch (matcher.match(uri)) {
case NUM1:
// 如果操作的数据属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/开头
return "vnd.android.cursor.dir/student";
case NUM2:
// 如果要操作的数据属于非集合类型数据,那么MIME类型字符串应该以vnd.android.cursor.item/开头
return "vnd.android.cursor.item/student";
default:
throw new IllegalArgumentException("Unknown URL " + uri);
}
} // 插入操作
@Override
public Uri insert(Uri uri, ContentValues values) {
long sid = 0; // 用于存储插入成功后的记录的id
switch (matcher.match(uri)) {
// content://come.demo.sqlite.studentprovider/t_student
case NUM1:
sid = db.insert("t_student", "sname", values);
// withAppendedId方法用于在uri后面追加一个sid的值
return ContentUris.withAppendedId(uri, sid);
// content://come.demo.sqlite.studentprovider/t_student/#
case NUM2:
sid = db.insert("t_student", "sname", values);
String path = uri.toString();
// 后面的id值更新
return Uri
.parse(path.substring(0, path.lastIndexOf("/") + 1) + sid);
default:
throw new IllegalArgumentException("Unknown URL " + uri);
}
} // 删除操作
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int count = 0; // 记录删除的结果
switch (matcher.match(uri)) {
// content://come.demo.sqlite.studentprovider/t_student
case NUM1:
count = db.delete("t_student", selection, selectionArgs);
break;
// content://come.demo.sqlite.studentprovider/t_student/#
case NUM2:
long sid = ContentUris.parseId(uri); // 从uri中获取id的值
String where = TextUtils.isEmpty(selection) ? "sid = ?" : selection
+ "sid = ?";
String params[] = new String[] { String.valueOf(sid) };
if (!TextUtils.isEmpty(selection) && selectionArgs != null) {
params = new String[selectionArgs.length + 1];
for (int i = 0; i < selectionArgs.length; i++) {
params[i] = selectionArgs[i];
}
params[selectionArgs.length + 1] = String.valueOf(sid);
}
count = db.delete("t_student", where, params);
break;
default:
throw new IllegalArgumentException("Unknown URL " + uri);
}
return count;
} // 更新操作
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int count = 0; // 记录修改的结果
switch (matcher.match(uri)) {
// content://come.demo.sqlite.studentprovider/t_student
case NUM1:
count = db.update("t_student", values, selection, selectionArgs);
break;
// content://come.demo.sqlite.studentprovider/t_student/#
case NUM2:
long sid = ContentUris.parseId(uri); // 从uri中获取id的值
String where = TextUtils.isEmpty(selection) ? "sid = ?" : selection
+ "sid = ?";
String params[] = new String[] { String.valueOf(sid) };
if (!TextUtils.isEmpty(selection) && selectionArgs != null) {
params = new String[selectionArgs.length + 1];
for (int i = 0; i < selectionArgs.length; i++) {
params[i] = selectionArgs[i];
}
params[selectionArgs.length + 1] = String.valueOf(sid);
}
count = db.update("t_student", values, where, params);
break;
default:
throw new IllegalArgumentException("Unknown URL " + uri);
}
return count;
} }

说明,上述程序是在之前写的sqlite基础上扩展的,不清楚的童鞋可以查看我的sqlite学习笔记ANDROID数据存储之SQLITE(二),DBOpenHelper为sqlite帮助类

(2)在AndroidManifest.xml文件中声明自己的Provider

 <provider android:name="com.demo.sqlite.provider.StudentProvider"
android:authorities="come.demo.sqlite.studentprovider"></provider>

至此,自定义内容提供者编写完成,提供了content://come.demo.sqlite.studentprovider/t_student和content://come.demo.sqlite.studentprovider/t_student/#两种方式来供外界使用,下一章将讲解其他应用程序如何来访问这个自定义的内容提供者

------------------------------------------------------------------------------------------分割线--------------------------------------------------------------------------------------------------------------------------------

课外扩充知识:

UriMatcher类和ContentUris类的介绍

因为Uri代表了要操作的数据,所以我们经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher和ContentUris

(1)UriMatcher类用于匹配Uri

//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//如果match()方法匹配content://come.demo.sqlite.studentprovider/person路径,返回匹配码为1
sMatcher.addURI("come.demo.sqlite.studentprovider", "person", 1);//添加需要匹配uri,如果匹配就会返回匹配码
//如果match()方法匹配content://come.demo.sqlite.studentprovider/person/230路径,返回匹配码为2
sMatcher.addURI("come.demo.sqlite.studentprovider", "person/#", 2);//#号为通配符
switch (sMatcher.match(Uri.parse("content://come.demo.sqlite.studentprovider/person/10"))) {
case 1
break;
case 2
break;
default://不匹配
break;
}

注册完需要匹配的Uri后,就可以使用sMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://come.demo.sqlite.studentprovider/person路径,返回的匹配码为1

(2)ContentUris类用于操作Uri路径后面的ID部分

  withAppendedId(uri, id)用于为路径加上ID部分

Uri uri = Uri.parse("content://come.demo.sqlite.studentprovider/person")
Uri resultUri = ContentUris.withAppendedId(uri, 10);
//生成后的Uri为:content://come.demo.sqlite.studentprovider/person/10

  parseId(uri)方法用于从路径中获取ID部分:

Uri uri = Uri.parse("content://come.demo.sqlite.studentprovider/person/10")
long personid = ContentUris.parseId(uri);//获取的结果为:10

android四大组件之ContentProvider(一)的更多相关文章

  1. Android 四大组件之" ContentProvider "

    前言 ContentProvider作为Android的四大组件之一,是属于需要掌握的基础知识,可能在我们的应用中,对于Activity和Service这两个组件用的很常见,了解的也很多,但是对Con ...

  2. Android四大组件之——ContentProvider(一)

    Android四大组件之--ContentProvider(一) 本人邮箱:JohnTsai.Work@gmail.com,欢迎交流讨论. 欢迎转载,转载请注明网址:http://www.cnblog ...

  3. 【Android开发日记】之入门篇(九)——Android四大组件之ContentProvider

    数据源组件ContentProvider与其他组件不同,数据源组件并不包括特定的功能逻辑.它只是负责为应用提供数据访问的接口.Android内置的许多数据都是使用ContentProvider形式,供 ...

  4. 初学android:四大组件之contentprovider

    一.ContentProvider的概念ContentProvider:为存储和获取数据提供统一的接口.可以在不同的应用程序之间共享数据.Android已经为常见的一些数据提供了默认的ContentP ...

  5. Android四大组件之contentProvider

    Activity,Service,broadcast and Contentprovider android 4 大组件. ContentProvider:使用: public class Image ...

  6. Android 四大组件之四(ContentProvider)

    ContentProvider调用关系: ContentProvider(数据提供者)是应用程序之间共享数据的一种接口机制,是一种更为高级的数据共享方法. ContentProvider可以指定需要共 ...

  7. android四大组件之ContentProvider(二)

    ContentProvider学习笔记 上一章节我们编写了自定义的一个StudentProvider,他提供了两种供外界访问数据的方式,content://come.demo.sqlite.stude ...

  8. Android四大组件之contentProvider(续)

    1.content provider与网页有何相似之处? contentProvider使用authority 同网站的域名类似 contentProvider还可以提供类似于网站的索引方式      ...

  9. [Android]Android四大组件之ContentProvider

    URI简介 URI(Universal Resource Identifier),又被称为"通用资源标志符". URI由许多部分所组成,示例及解说如下: Content URIs介 ...

随机推荐

  1. lhgdialog: iframe页面里面的,确定,关闭、取消按钮的操作

    lhgdialog: iframe页面里面的,确定,关闭.取消按钮的操作 如果你正在用lhgdialog,用他人iframe,或者 content:'url:http://www.baidu.com/ ...

  2. maven-surefire-plugin的乱码问题

    今天项目中出现奇怪问题,在eclipse中直接运行TestNG时,全部都OK,但是执行mvn test时却失败.观察其输出日志,发现有乱码,怀疑是乱码导致. 最终在官网发现蛛丝马迹. maven-su ...

  3. 运行Python脚本的方法

    1.安装完Python后,添加环境变量---在系统变量中找到Path ,点击编辑把你的python安装目录放到里面,注意环境变量之间用";"隔开.打开CMD,在CMD命令行中,输入 ...

  4. python--安装PIL

    PIL:Python Imaging Library,已经是Python平台事实上的图像处理标准库了.PIL功能非常强大,但API却非常简单易用. 安装PIL 在Debian/Ubuntu Linux ...

  5. int转string

    #include<iostream> #include<sstream> #include<string> using namespace std; int mai ...

  6. 51nod 1135 原根

    题目链接:51nod 1135 原根 设 m 是正整数,a是整数,若a模m的阶等于φ(m),则称 a 为 模m的一个原根.(其中φ(m)表示m的欧拉函数) 阶:gcd(a,m)=1,使得成立的最小的 ...

  7. http 网络请求

    /**         * 用 HttpClient 的 Get 请求访问服务器         *          * @param url_path         * @param userN ...

  8. Android VideoView播放视频

    今天介绍一下Android的视频播放控件VideoView,下面介绍一下VideoView的使用步骤: 1.在界面布局中定义VideoView组件,或者在程序中创建VideoView组件. 2.调用V ...

  9. asp.net导出word(word2007)

    1.只能导出成word2007格式(.docx),可直接导出到客户端 2.服务器上不需要装任何东西,也没有权限限制,比较适合导出表格(支持图片) 3.需要一个国外的DocX.dll插件 4.需要添加引 ...

  10. 基于Twemproxy的Redis集群搭建以及想法

    基于Twemproxy的Redis集群方案(转) redis3.0 已经发布了几个月了,但是我这等菜鸟到网上还是没有找到很好的关于搭建redis3.0集群的文章,而且好像很多公司的redis版本还保持 ...