ContentProvider介绍

ContentProvider是不同应用程序之间进行交换数据的标志API

也就是说:一个应用程序通过ContentProvider暴露自己的数据操作接口,那么无论该应用是否启动(一定部署),其它应用程序能够通过该接口来操作该应用的内部数据,包含添加数据,删除数据,改动数据。查询数据等。

当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就能够向其它应用共享其数据。

尽管使用其它方法也能够对外共享数据,但数据訪问方式会因数据存储的方式而不同

如:採用文件方式对外共享数据,须要进行文件操作读写数据。

採用sharedpreferences共享数据。须要使用sharedpreferences API读写数据。

而使用ContentProvider共享数据的优点是统一了数据訪问方式。

通过ContentProvider对外共享数据步骤:

继承ContentProvider并重写以下方法

public class PersonContentProvider extends ContentProvider{

public boolean onCreate()

public Uri insert(Uri uri, ContentValues values)

public int delete(Uri uri, String selection, String[] selectionArgs)

public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)

public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

public String getType(Uri uri)

}

方法介绍

public boolean onCreate()

在UserContentProvider创建之后,就会被调用,当其它应用程序第一次訪问contentPrivider时。该ContentProvider就会被创建出来

public String getType(Uri uri)

返回操作的类型 假设操作多条记录那么MINE类型vnd.android.cursor.dir/开头

假设操作的数据仅仅有一条记录那么MINE类型vnd.android.cursor.item/开头

public Uri insert(Uri uri, ContentValues values)

插入操作

public int delete(Uri uri, String selection, String[] selectionArgs)

删除操作

public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)

改动操作

public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

查询操作


在AndroidManifest.xml使用<provider>对该ContentProvider进行配置

为了能让其它应用找到该ContentProvider 。 ContentProvider 採用了authorities(主机名/域名)对它进行唯一标识,你能够把 ContentProvider看作是一个站点(想想,站点也是提供数据者),authorities 就是他的域名:

<manifest .... >

    <application android:icon="@drawable/icon" android:label="@string/app_name">

        <provider android:name=".PersonContentProvider" android:authorities="cn.itcast.provider.personprovider"/>

    </application>

</manifest>

注意:一旦应用继承了ContentProvider类,后面我们就会把这个应用称为ContentProvider(内容提供者)。

Uri介绍

Uri代表了要操作的数据

Uri主要包括了两部分信息:
  1. 须要操作的ContentProvider 。
  2. 对ContentProvider中的什么数据进行操作

Uri组成部分


  • scheme: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就充当的这个角色,和我们訪问的url一样。例如以下:

URL:    http://www.baidu.com/index.html 
http://:
http协议訪问站点
www.baidu.com域名部分
 /index.html:站点资源 
URI:     content://www.csdn.com.provider.userContentProvider/user
content://android的ContentProvider的规定

www.csdn.com.provider.userContentProvider:文件汇中自己配置的authorities

user: 资源部分(数据部分)当訪问者须要訪问不同的资源时,这个部分是动态改变.这个部分能够自定义


parse()

假设要把一个字符串转换成Uri
Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person")

操作Uri

由于Uri代表了要操作的数据,所以我们常常须要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类。分别为UriMatcher 和ContentUris 。掌握它们的使用。会便于我们的开发工作。

UriMatcher类

  • uriMatcher.addURI(authority, path, code):匹配码是调用addURI()方法传入的第三个參数

    • 參数一authority:定义的authority路径
    • 參数二path:URI路径
    • 參数三code:返回的匹配码
  • 注冊完须要匹配的Uri后,就能够使用sMatcher.match(uri)方法对输入的Uri进行匹配,假设匹配就返回匹配码。
UriMatcher类用于匹配Uri。它的使用方法例如以下:

把你须要匹配Uri路径所有给注冊上,例如以下:

//常量UriMatcher.NO_MATCH表示不匹配不论什么路径的返回码

UriMatcher  sMatcher = new UriMatcher(UriMatcher.NO_MATCH);

//假设match()方法匹配content://cn.itcast.provider.personprovider/person路径,返回匹配码为1

sMatcher.addURI(“cn.itcast.provider.personprovider”, “person”, 1);//加入须要匹配uri。假设匹配就会返回匹配码

//假设match()方法匹配content://cn.itcast.provider.personprovider/person/230路径,返回匹配码为2

sMatcher.addURI(“cn.itcast.provider.personprovider”, “person/#”, 2);//#号为通配符

switch (sMatcher.match(Uri.parse("content://cn.itcast.provider.personprovider/person/10"))) { 

case 1

break;

case 2

break;

default://不匹配

break;

}

ContentUris类

ContentUris类用于获取Uri路径后面的ID部分,它有两个比較有用的方法:


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

    • Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person")
    • Uri resultUri = ContentUris.withAppendedId(uri, 10);
    • //生成后的Uri为:content://cn.itcast.provider.personprovider/person/10
  • parseId(uri)方法用于从路径中获取ID部分:
    • Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person/10")
    • long personid = ContentUris.parseId(uri);
    • //获取的结果为:10

ContentProvider中方法实现步骤

  1. 继承ContentProvider类
  2. 声明操作的标志
  3. 定义uri解析返回的匹配码
  4. 使用UriMatcher类匹配Uri
  5. 在oncreate()中实例化数据库操作对象
  6. 查询方法
    1. 匹配URI 进行推断
    2. 匹配成功进行查询
  7. 加入方法
    1. 匹配URI 进行推断
    2. 匹配成功进行加入
    3. 返回:通过ContentUris.withAppendedId加入唯一的id值
  8. 删除方法
    1. 匹配URI 进行推断
    2. 匹配成功进行删除
    3. 关闭数据库
    4. 返回:删除的行数
  9. 改动方法
    1. 匹配URI 进行推断
    2. 匹配成功进行改动
    3. 关闭数据库
    4. 返回:改动的行数
ContentProvider中的增删改查都是依据android封装好的CURD

ContentProvider源代码:
package com.example.android_sqlite.provider;

import com.example.android_sqlite.database.DatabaseHelper;

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; public class UserContentProvider extends ContentProvider {
// 1.操作的标志
private static final String AUTHORITIE = "www.csdn.com.provider.userContentProvider"; // 2.定义uri解析返回的匹配码
private static final int QUERY = 1;
private static final int INSERT = 2;
private static final int UPDATE = 3;
private static final int DELETE = 4; private static UriMatcher uriMatcher;
private DatabaseHelper dh; // 3.使用UriMatcher类匹配Uri
static {
//实例化UriMatcher对象。常量UriMatcher.NO_MATCH表示不匹配不论什么路径的返回码
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// 匹配的结果码
uriMatcher.addURI(AUTHORITIE, "query", QUERY);
uriMatcher.addURI(AUTHORITIE, "insert", INSERT);
uriMatcher.addURI(AUTHORITIE, "update", UPDATE);
uriMatcher.addURI(AUTHORITIE, "delete", DELETE);
} /**
* 在UserContentProvider创建之后,就会被调用,当其它应用程序第一次訪问contentPrivider时。
* 该ContentProvider就会被创建出来
*/
@Override
public boolean onCreate() {
dh = new DatabaseHelper(getContext());
return false;
} /**
* URL:http://www.baidu.com/index.html http://: http协议訪问站点
* www.baidu.com:域名部分 /index.html:站点资源
*
* URI:content://www.csdn.com.provider.userContentProvider/user
* content://android的ContentProvider的规定
* www.csdn.com.provider.userContentProvider:文件汇中自己配置的authorities
* user:资源部分(数据部分)当訪问者须要訪问不同的资源时,这个部分是动态改变.这个部分能够自定义
*
* UriMatcher:匹配uri
*/
/**
* 查询方法
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) { Cursor c = null;
// 匹配URI 进行推断
if (uriMatcher.match(uri) == QUERY) {
SQLiteDatabase db = dh.getReadableDatabase();
c = db.query("users", projection, selection, selectionArgs, null,
null, sortOrder);
} else {
System.out.println("查询操作的uri不匹配");
}
return c;
} /**
* 返回操作的类型 假设操作多条记录那么MINE类型vnd.android.cursor.div/开头
* 假设操作的数据仅仅有一条记录那么MINE类型vnd.android.cursor.item/开头
*/
@Override
public String getType(Uri arg0) {
return null; } /**
* 插入操作
*/
@Override
public Uri insert(Uri uri, ContentValues values) {
long rowId = 0;
if (uriMatcher.match(uri) == INSERT) {
SQLiteDatabase db = dh.getReadableDatabase();
rowId = db.insert("users", null, values);
db.close();
} else {
System.out.println("插入不匹配");
}
//通过ContentUris.withAppendedId增加唯一的id值
return ContentUris.withAppendedId(uri, rowId);
} /**
* 更新操作
*/
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
//更新几行
int count = 0;
if (uriMatcher.match(uri) == UPDATE) {
SQLiteDatabase db = dh.getWritableDatabase();
count = db.update("users", values, selection, selectionArgs);
db.close();
}
return count;
} /**
* 删除操作
*/
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
//删除几行
int count = 0;
if (uriMatcher.match(uri) == DELETE) {
SQLiteDatabase db = dh.getWritableDatabase();
count = db.delete("users", selection, selectionArgs);
db.close();
}
return count;
} }

AndroidManifest.xml


<?

xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android_sqlite"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" /> <instrumentation
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.example.android_sqlite" >
</instrumentation> <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.android_sqlite.MainActivitysss"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity> <uses-library android:name="android.test.runner" />
<!-- 配置ContentProvider -->
<provider
android:name=".provider.UserContentProvider"
android:authorities="www.csdn.com.provider.userContentProvider"
android:exported="true" >
</provider>
</application> </manifest>






赵雅智_ContentProvider的更多相关文章

  1. 赵雅智_Fragment生命周期

    官网帮助文档链接:  http://developer.android.com/guide/components/fragments.html 主要看两张图.和跑代码 一,Fragment的生命周 w ...

  2. 赵雅智:js知识点汇总

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhhb3lhemhpMjEyOQ==/font/5a6L5L2T/fontsize/400/fill/I0 ...

  3. 赵雅智_ListView_BaseAdapter

    Android界面中有时候须要显示略微复杂的界面时,就须要我们自己定义一个adapter,而此adapter就要继承BaseAdapter,又一次当中的方法. Android中Adapter类事实上就 ...

  4. 赵雅智_BroadcastReceiver电话监听

    AndroidManifest.xml 注冊广播接收者 加入权限 <?xml version="1.0" encoding="utf-8"?> &l ...

  5. 赵雅智_BroadcastReceiver

    BroadcastReceiver  用于接收程序(包含用户开放的程序和系统内建程序)所发出的Broadcast intent 耗电量 开机启动 窃取别人短信 窃取别人电话 开发: 创建须要启动的Br ...

  6. 赵雅智:service_startService生命周期

    案例演示 布局文件 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xm ...

  7. 赵雅智_BroadcastReceiver短信监听

    AndroidManifest.xml 注冊广播接收者 加入权限 <?xml version="1.0" encoding="utf-8"?> &l ...

  8. 赵雅智_Android编码规范

    凝视 导入mycodetemplates.xml统一凝视样式 须要加凝视的地方 类凝视(必加) 方法凝视(必加) 块凝视主要是数据结构和算法的描写叙述(必加) 类成员变量和常量凝视(选择性加入) 单行 ...

  9. 赵雅智:service与訪问者之间进行通信,数据交换

    服务类 中间人:service服务中的bind对象 创建中间人并通过onBinder方法的return暴露出去 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQ ...

随机推荐

  1. 关于python中使用mongodb模块,save和insert的小问题

    今天写python脚本的时候发现这样一个问题: import os , string , datetime ,pymongo; conn = pymongo.Connection("127. ...

  2. Nosql释义

    NoSQL不是产品,是一项运动        ---->NoSQL(NoSQL = Not Only SQL ),意即反SQL运动,是一项全新的数据库革命性运动,早期就有人提出,发展至2009年 ...

  3. Delphi 为什么它提示PCHAR是不安全的类型呢 Unsafe type 'PChar'

    DELPHI7已经考虑到了移植到点NET的问题,在点NET里,指针是不安全的.至于为什么有的人遇到,有的人没有遇到,那是因为各人的编译选项不同.在Project菜单下选Options“Compiler ...

  4. Windows Phone 离主流系统还很远

    调查机构 Kantar Worldpanel 在本月发布全球智能手机份额报告.报告显示,五月份除德国和澳大利亚出现下滑,Windows Phone 的市场份额在不少国家都实现增长. 英国,4.1% 升 ...

  5. IOS CAShapeLayer CAGradientLayer UIBezierPath 使用实例

    CGRect rect = CGRectMake(100, 100, 100, 100); UIView * bgView = [[UIView alloc]initWithFrame:rect]; ...

  6. gcc编译器基本命令和vi编辑器2

    !1 os fen时 看电影 聊天.支持多核处理器 分任务 已经绝迹cpu Trobe c 分任务操作系统三大组成部分内核,命令解释器(shell外壳),文件系统2修改文件日期或(创建文件)命令:to ...

  7. XNA Game Studio4.0 Programming 随便读,随便记。

    一.精灵和2D图形 1.什么是2D ? 2D可以理解为 two-Dimentionanl  , 2-dimentional 的缩写. 意就是两维的,比如 数学中的 直角坐标系 所能描述的就是一个2D的 ...

  8. 在Ubuntu6.06 在搭建SVN服务器及在windows建立svn+ssh客户端 (续)

    接上篇.本篇主要介绍windows下建立svn+ssh客户端. 9.在windows下安装svn客户端,则需安装“TortoiseSVN”.“Puttygen”和“Pageant”    9.1.下载 ...

  9. 初识JAVA(【面向对象】:pub/fri/pro/pri、封装/继承/多态、接口/抽象类、静态方法和抽象方法;泛型、垃圾回收机制、反射和RTTI)

    JAVA特点: 语法简单,学习容易 功能强大,适合各种应用开发:J2SE/J2ME/J2EE 面向对象,易扩展,易维护 容错机制好,在内存不够时仍能不崩溃.不死机 强大的网络应用功能 跨平台:JVM, ...

  10. Tasks Queues and Cron Jobs(任务队列和时钟守护作业)

    一个网络应用必须迅速响应网络请求,一般要小于1s,最好是几十微秒,以便为坐在浏览器前面的用户提供一个流畅的体验.这就给不了应用太多的时间来处理工作.有时会是有更多的工作要做而不是有时间来做它.< ...