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. ubuntu下oracle数据的导入,导入oracle数据库命令行
  2. Boost:由内部绑定的值返回的智能指针的测试程序
  3. 如何在mac上搭建sqli-labs
  4. Redis高效性探索--线程IO模型,通信协议
  5. 陶陶摘苹果(升级版)(洛谷-P1478)
  6. python点击屏幕_Python屏幕操作
  7. Android 实现ListView的A-Z字母排序和过滤搜索功能,实现汉字转成拼音
  8. 如何卸载zabbix且删除
  9. oracle主机自增,Oracle中实现ID自增
  10. 聊聊我的 ACL2020 论文
  11. 强化学习_Deep Q Learning(DQN)_代码解析
  12. 计算机网络技术基础试卷2,《计算机网络基础考试2》试题与答案
  13. [暗黑破坏神2]PLUGY与HACKMAP共存
  14. DCN神州数码无线理论与配置逻辑
  15. 我们最畅销的30本好书,都在这了
  16. 2019年那些成年人的崩溃瞬间,看着看着就哭了
  17. Java 语言被很多人抱怨语法繁琐、开发效率低、体系繁杂而笨重,为什么还有这么强的生命力,尤其是在企_-Chaz-_新浪博客
  18. 草蛋的Android studio 居然让我搞了好几天 真是智障啊non-zero exit value 2
  19. woocommerce 新增一个支付网关
  20. opencv-python傅里叶变换以及逆变换

热门文章

  1. 人人都是 DBA(VII)B 树和 B+ 树
  2. 雷观(十一):接私活有利有弊,我们应该根据自己的实际情况选择接私活
  3. Java的poi技术读取和导入Excel
  4. SendTextMessage 等方便的消息发送函数
  5. xmpp 服务器配置 open fire for windows 及 spark 测试
  6. GCT之数学公式(代数部分)
  7. [SQL Server]Index/deadlock
  8. mariadb编译安装流程
  9. TxQueryRunner-JDBC小工具
  10. HDU 5411 CRB and Puzzle (2015年多校比赛第10场)