Content Provider 属于Android应用程序的组件之一,作为应用程序之间唯一的共享数据的途径,Content Provider 主要的功能就是存储并检索数据以及向其他应用程序提供访问数据的借口。

Android 系统为一些常见的数据类型(如音乐、视频、图像、手机通信录联系人信息等)内置了一系列的 Content Provider, 这些都位于android.provider包下。持有特定的许可,可以在自己开发的应用程序中访问这些Content Provider。

让自己的数据和其他应用程序共享有两种方式:创建自己的Content Provier(即继承自ContentProvider的子类)  或者是将自己的数据添加到已有的Content Provider中去,后者需要保证现有的Content Provider和自己的数据类型相同且具有该 Content Provider的写入权限。对于Content Provider,最重要的就是数据模型(data model) 和 URI。 
   
   1.数据模型 
    Content Provider 将其存储的数据以数据表的形式提供给访问者,在数据表中每一行为一条记录,每一列为具有特定类型和意义的数据。每一条数据记录都包括一个 "_ID" 数值字段,改字段唯一标识一条数据。

2.URI 
    URI,每一个Content Provider 都对外提供一个能够唯一标识自己数据集(data set)的公开URI, 如果一个Content Provider管理多个数据集,其将会为每个数据集分配一个独立的URI。所有的Content Provider 的URI 都以"content://" 开头,其中"content:"是用来标识数据是由Content Provider管理的 schema。

在几乎所有的Content Provider 的操作中都会用到URI,因此一般来讲,如果是自己开发的Content Provider,最好将URI定义为常量,这样在简化开发的同时也提高了代码的可维护性。

首先来介绍如何访问Content Provider中的数据,访问 Content Provider中的数据主要通过ContentResolver对象,ContentResolver类提供了成员方法可以用来对Content Provider 中的数据进行查询、插入、修改和删除等操作。 以查询为例,查询一个 Content Provider 需要掌握如下的信息。

唯一标识Content Provider 的URI 
      需要访问的数据字段名称。 
      该数据字段的数据类型

提示: 如果需要访问特定的某条数据记录,只需该记录的ID 即可。

查询Content Provider的方法有两个:ContentResolver的query() 和 Activity 对象的 managedQuery(),二者接收的参数均相同,返回的都是Cursor 对象,唯一不同的是 使用managedQuery 方法可以让Activity 来管理 Cursor 的生命周期。

被管理的Cursor 会在 Activity进入暂停状态的时候调用自己的 deactivate 方法自行卸载,而在Activity回到运行状态时会调用自己的requery 方法重新查询生成的Cursor对象。如果一个未被管理的Cursor对象想被Activity管理,可以调用Activity的 startManagingCursor方法来实现。

 

Android应用程序可以使用文件或SqlLite数据库来存储数据。Content Provider提供了一种多应用间数据共享的方式,比如:联系人信息可以被多个应用程序访问。Content Provider是个实现了一组用于提供其他应用程序存取数据的标准方法的类。

应用程序可以在Content Provider中执行如下操作:
查询数据

修改数据

添加数据

删除数据


MainActivity.java

代码package com.amaker.ch10.app;import android.app.Activity;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;import com.amaker.ch10.app.Employees.Employee;public class MainActivity extends Activity {@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);// 添加insert();// 查询query();// 更新update();// 查询query();// 删除del();// 查询query();}// 删除方法private void del(){// 删除ID为1的记录Uri uri = ContentUris.withAppendedId(Employee.CONTENT_URI, 1);// 获得ContentResolver,并删除getContentResolver().delete(uri, null, null);}// 更新private void update(){// 更新ID为1的记录Uri uri = ContentUris.withAppendedId(Employee.CONTENT_URI, 1);ContentValues values = new ContentValues();// 添加员工信息values.put(Employee.NAME, "hz.guo");values.put(Employee.GENDER, "male");values.put(Employee.AGE,31);// 获得ContentResolver,并更新getContentResolver().update(uri, values, null, null);}// 查询private void query(){// 查询列数组String[] PROJECTION = new String[] { Employee._ID,         // 0Employee.NAME,         // 1Employee.GENDER,     // 2Employee.AGE         // 3};// 查询所有备忘录信息Cursor c = managedQuery(Employee.CONTENT_URI, PROJECTION, null,null, Employee.DEFAULT_SORT_ORDER);// 判断游标是否为空if (c.moveToFirst()) {// 遍历游标for (int i = 0; i < c.getCount(); i++) {c.moveToPosition(i);// 获得姓名String name = c.getString(1);String gender = c.getString(2);int age = c.getInt(3);// 输出日志Log.i("emp", name+":"+gender+":"+age);}}}// 插入private void insert(){// 声明UriUri uri = Employee.CONTENT_URI;// 实例化ContentValuesContentValues values = new ContentValues();// 添加员工信息values.put(Employee.NAME, "amaker");values.put(Employee.GENDER, "male");values.put(Employee.AGE,30);// 获得ContentResolver,并插入getContentResolver().insert(uri, values);}
}

Employees.java

代码package com.amaker.ch10.app;import android.net.Uri;
import android.provider.BaseColumns;/*** 通讯录常量类*/
public final class Employees {// 授权常量public static final String AUTHORITY = "com.amaker.provider.Employees";private Employees() {}// 内部类public static final class Employee implements BaseColumns {// 构造方法private Employee() {}// 访问Uripublic static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/employee");// 内容类型public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.amaker.employees";public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.amaker.employees";// 默认排序常量public static final String DEFAULT_SORT_ORDER = "name DESC";// 按姓名排序// 表字段常量public static final String NAME = "name";                    // 姓名public static final String GENDER= "gender";                // 性别public static final String AGE = "age";                     // 年龄}
}

EmployeeProvider.java

代码package com.amaker.ch10.app;import java.util.HashMap;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.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;import com.amaker.ch10.app.Employees.Employee;public class EmployeeProvider extends ContentProvider{// 数据库帮助类private DBHelper dbHelper;// Uri工具类private static final UriMatcher sUriMatcher;// 查询、更新条件private static final int EMPLOYEE = 1;private static final int EMPLOYEE_ID = 2;// 查询列集合private static HashMap<String, String> empProjectionMap;static {// Uri匹配工具类sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);sUriMatcher.addURI(Employees.AUTHORITY, "employee", EMPLOYEE);sUriMatcher.addURI(Employees.AUTHORITY, "employee/#", EMPLOYEE_ID);// 实例化查询列集合empProjectionMap = new HashMap<String, String>();// 添加查询列empProjectionMap.put(Employee._ID, Employee._ID);empProjectionMap.put(Employee.NAME, Employee.NAME);empProjectionMap.put(Employee.GENDER, Employee.GENDER);empProjectionMap.put(Employee.AGE, Employee.AGE);}// 创建是调用public boolean onCreate() {// 实例化数据库帮助类dbHelper = new DBHelper(getContext());return true;}// 添加方法public Uri insert(Uri uri, ContentValues values) {// 获得数据库实例SQLiteDatabase db = dbHelper.getWritableDatabase();// 插入数据,返回行IDlong rowId = db.insert(DBHelper.EMPLOYEES_TABLE_NAME, Employee.NAME, values);// 如果插入成功返回uriif (rowId > 0) {Uri empUri = ContentUris.withAppendedId(Employee.CONTENT_URI, rowId);getContext().getContentResolver().notifyChange(empUri, null);return empUri;}return null;}// 删除方法public int delete(Uri uri, String selection, String[] selectionArgs) {// 获得数据库实例SQLiteDatabase db = dbHelper.getWritableDatabase();// 获得数据库实例int count;switch (sUriMatcher.match(uri)) {// 根据指定条件删除case EMPLOYEE:count = db.delete(DBHelper.EMPLOYEES_TABLE_NAME, selection, selectionArgs);break;// 根据指定条件和ID删除case EMPLOYEE_ID:String noteId = uri.getPathSegments().get(1);count = db.delete(DBHelper.EMPLOYEES_TABLE_NAME, Employee._ID + "=" + noteId+ (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs);break;default:throw new IllegalArgumentException("错误的 URI " + uri);}getContext().getContentResolver().notifyChange(uri, null);return count;}// 获得类型public String getType(Uri uri) {return null;}// 查询方法public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {SQLiteQueryBuilder qb = new SQLiteQueryBuilder();switch (sUriMatcher.match(uri)) {// 查询所有case EMPLOYEE:qb.setTables(DBHelper.EMPLOYEES_TABLE_NAME);qb.setProjectionMap(empProjectionMap);break;// 根据ID查询case EMPLOYEE_ID:qb.setTables(DBHelper.EMPLOYEES_TABLE_NAME);qb.setProjectionMap(empProjectionMap);qb.appendWhere(Employee._ID + "=" + uri.getPathSegments().get(1));break;default:throw new IllegalArgumentException("Uri错误! " + uri);}// 使用默认排序String orderBy;if (TextUtils.isEmpty(sortOrder)) {orderBy = Employee.DEFAULT_SORT_ORDER;} else {orderBy = sortOrder;}// 获得数据库实例SQLiteDatabase db = dbHelper.getReadableDatabase();// 返回游标集合Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);c.setNotificationUri(getContext().getContentResolver(), uri);return c;}// 更新方法public int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) {// 获得数据库实例SQLiteDatabase db = dbHelper.getWritableDatabase();int count;switch (sUriMatcher.match(uri)) {// 根据指定条件更新case EMPLOYEE:count = db.update(DBHelper.EMPLOYEES_TABLE_NAME, values, selection, selectionArgs);break;// 根据指定条件和ID更新case EMPLOYEE_ID:String noteId = uri.getPathSegments().get(1);count = db.update(DBHelper.EMPLOYEES_TABLE_NAME, values, Employee._ID + "=" + noteId+ (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs);break;default:throw new IllegalArgumentException("错误的 URI " + uri);}getContext().getContentResolver().notifyChange(uri, null);return count;}}

app/DBHelper.java

代码package com.amaker.ch10.app;import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import com.amaker.ch10.app.Employees.Employee;
/*** * 数据库工具类*/
public class DBHelper extends SQLiteOpenHelper{// 数据库名称常量private static final String DATABASE_NAME = "Employees.db";// 数据库版本常量private static final int DATABASE_VERSION = 1;// 表名称常量public static final String EMPLOYEES_TABLE_NAME = "employee";// 构造方法public DBHelper(Context context) {// 创建数据库super(context, DATABASE_NAME,null, DATABASE_VERSION);}// 创建时调用public void onCreate(SQLiteDatabase db) {db.execSQL("CREATE TABLE " + EMPLOYEES_TABLE_NAME + " ("+ Employee._ID + " INTEGER PRIMARY KEY,"+ Employee.NAME + " TEXT,"+ Employee.GENDER + " TEXT,"+ Employee.AGE + " INTEGER"+ ");");}// 版本更新时调用public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {// 删除表db.execSQL("DROP TABLE IF EXISTS employee");onCreate(db);}}

AndroidManifest.xml

代码<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.amaker.ch10.app"android:versionCode="1"android:versionName="1.0"><application android:icon="@drawable/icon" android:label="@string/app_name"><provider android:name="EmployeeProvider" android:authorities="com.amaker.provider.Employees"/><activity android:name=".MainActivity"android:label="@string/app_name"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application><uses-sdk android:minSdkVersion="3" /></manifest>

Content Provide详解相关推荐

  1. Android Content Provider详解-实现ContentProvider MIME 类型

    转载至:http://www.2cto.com/kf/201212/179560.html 实现ContentProvider MIME 类型   ContentProvider 有两个方法返回MIM ...

  2. html中content属性,CSS3的content属性详解

    CSS中主要的伪元素有四个:before/after/first-letter/first-line,在before/after伪元素选择器中,有一个content属性,能够实现页面中的内容插入. 插 ...

  3. vue 中provide的用法_Vue多级组件provide/inject使用详解

    这次给大家带来Vue多级组件provide/inject使用详解,Vue多级组件provide/inject使用的注意事项有哪些,下面就是实战案例,一起来看一下. provide / inject 是 ...

  4. 详解CSS3中新增的内容属性:content

    详解CSS3中新增的内容属性:content 1. 用法: content属性用于插入生成的内容,常和:before选择器和:after选择器配合使用,将生成的内容放在一个元素内容的前面或后面. 2. ...

  5. python中的content方法_对python requests的content和text方法的区别详解

    问题: 一直在想requests的content和text属性的区别,从print 结果来看是没有任何区别的 看下源码: @property def text(self): ""& ...

  6. Elastricsearch 索引操作详解(快速入门、索引管理、映射详解、索引别名)

    一.快速入门 1. 查看集群的健康状况 http://localhost:9200/_cat http://localhost:9200/_cat/health?v 说明:v是用来要求在结果中返回表头 ...

  7. Android中measure过程、WRAP_CONTENT详解以及 xml布局文件解析流程浅析

    转自:http://www.uml.org.cn/mobiledev/201211221.asp 今天,我着重讲解下如下三个内容: measure过程 WRAP_CONTENT.MATCH_PAREN ...

  8. Android中measure过程、WRAP_CONTENT详解以及xml布局文件解析流程浅析(下)

       本文原创, 转载请注明出处:http://blog.csdn.net/qinjuning 上篇文章<<Android中measure过程.WRAP_CONTENT详解以及xml布局文 ...

  9. 最全的jquery datatables api 使用详解

    https://www.cnblogs.com/amoniyibeizi/p/4548111.html 最全的jquery datatables api 使用详解 学习可参考:http://www.g ...

最新文章

  1. SPRING 事务管理说明
  2. mysql的insert语法_mysql insert 语法
  3. PHP中abstract 和 interface的区别
  4. asp.net core web api之异常
  5. 网页边框和网页文字阴影
  6. python中psum是什么意思_python中**是什么
  7. SAP License:SAP中的权限与破解
  8. 敏捷开发般若敏捷系列之五:如何推广敏捷(中)(无寿者,回报,破我执)...
  9. BZOJ2241 [SDOI2011]打地鼠 【模拟】
  10. 《Android框架揭秘》——2.5节应用程序Framework源码级别调试
  11. Python基础 by.肖洪福
  12. 努比亚手机安装linux,努比亚红魔5G电竞手机将发布;Linux版荣耀MagicBook降价促销...
  13. upx壳的一些简单脱壳,望大牛勿喷。
  14. 脂肪秤方案中测脂模块如何实现BIA测量法功能?
  15. 用js:字符串数组中每一项的长度。将字符串数组用 | 符号分割。有序数组插入排序插入数组。猴子选大王
  16. 如何创建数据链接文件
  17. Linux Crontab执行hadoop命令脚本失败
  18. php编译安装, 编译安装nginx, yum安装nginx, nginx虚拟主机,默认虚拟主机
  19. 深度学习与计算机视觉-6章 Python-OpenCV
  20. 从 EuRoC MAV Dataset 的 .zip 文件生成 .bag 的 python 脚本

热门文章

  1. iOS学习资源(一)
  2. vue实现进入页面表单聚焦
  3. 部署 instance 到 OVS vlan100 - 每天5分钟玩转 OpenStack(138)
  4. window系统快捷键
  5. MSSQL 修改数据库的排序规则
  6. (电影播放器)MPMoviePlayerController
  7. SetProcessWorkingSetSize 降低程序运行内存
  8. 好久不用的viewport
  9. SpringBoot集成全局异常处理
  10. Unity3D Instantiate慢的问题