安卓开发_深入理解Content Provider
一、Content Provider概述
Content Provider用于保存和获取数据,并使其对所有应用程序可见,这是不同应用程序之间共享数据的唯一方式,因为在Android中没有提供所有应用可以共同访问的公共存储区域
1、 Content Provider内部的数据如何保存是由其设计者决定的,而所有的的Content Provider都实现一组通用的方法,用来提供数据的增删改查操作
2、 客户端如果要使用这些操作方法,可以通过ContentProvider对象实现对 Content Provider的操作,而开发人员可以通过调用getContentResolver()方法来获得ContentProvider对象
即:ContentResolver cr = getContentProvider();
3、 不同进程之间的通信由ContentResolver类和ContentProvider类处理
二、Content Provider提供数据的数据模型
_ID |
NAME |
AGE |
001 |
Alice |
17 |
002 |
Mark |
20 |
003 |
Tom |
11 |
可以看出使用的是基于数据库模型的简单表格来提供其中的数据 行:记录 列:字段
*每条记录都包含一个_ID字段,用于在表中唯一标识该记录
ID字段前包含一个下划线_ ,这是必须有的,不能不写
三、URI
1、 每个Content Provider提供公共的URI(使用URI类包装)来唯一标识其数据集
2、 URI常量用于所有与Content Provider的交互,每个Content Provider方法都是用URI作为方法的第一个参数,这个参数(URI)用来标识ContentResolver应该使用Content Provider中的哪一个数据表
3、 URI: content://com.xqx.mycontent/dba/010
(1)content:// :标准的前缀,用于标识该数据由Content Provider管理,固定值,不用修改
(2)com.xqx.mycontent :URI的authority部分,用于标识Content Provider,在清单文件的<provider>元素的authority属性中声明该authority ,对于第三方应用,该部分为完整的类名(全部小写字母)
(3)/dba :路径部分,用于决定哪类数据被请求,如果Content Provider只提供一种数据类型,则可省略该部分、如果提供多种类型,则由多部分组成
(4)/010 :被请求的特定记录的ID ,如果请求的记录不限于单条记录(比如查询全部字段),该部分不用写
四、预定义Content Provider
1、 安卓系统提供了很多预定义的Content Provider(声音,联系人,通话记录等)
Eg:
Browser :读取或修改书签,浏览历史或网络搜索
CallLog :查看或更新通话记录
Contacts: :获取修改或保存联系人信息
MediaStore:访问图片视频音乐等
2、 查询数据
如果想查询Content Provider数据,必须需要三个信息
(1) 标识该Content Provider的URI
(2) 需要查询的数据字段的名称
(3) 字段值数据的类型
*如果查询特定的记录,则还需要提供该记录的ID值
为了限制返回一条数据,可以在URI结尾添加要操作记录的ID,
Content://…./003
实现该功能可以使用静态方法ContentUris.withAppendedId(),返回值为一个增加了ID的URI对象
获得数据用Cursor对象处理,它能向前或向后遍历整个查询结果集。
3、 增加记录
(1) 向ContentProvider中添加数据,需要使用ContentValues对象建立键值对映射,键位Content Provider中的字段,值为要添加的值
(2) 调用ContentResolver.insert(URI,value);
第一个参数为要操作的ContentProvider唯一标识的URI,第二个参数为ContentValues映射 ,该方法返回添加记录的完整的URI
4、 删除记录
(1)需要调用int delete (Uri url, String where, String[] selectionArgs)方法 ,第一个为要操作的URI ,第二个为删除的条件,第三个参数为填充值
int delete (Uri url, “_id=?”, 11) 为删除URI 中id为11的记录
五、 自定义Content Provider
1、 我们从上面了解了开发人员可以使用系统给定的ContentProvide
当然我们也可以自定义ContentProvider来共享自己的数据(当然也可以使用系统预定义的ContentProvider,管理相同的数据并且有写入权限,也可修改对应数据)
自定义ContentProvider步骤
(1)、建立数据存储系统
Android提供了SQLiteOpenHelper 类帮助创建数据库,SQLiteDatabase类帮助管理数据库
(2)、继承ContentProvider
需要重写6个抽象方法
方法 |
说明 |
|
用于初始化provider |
query() |
返回数据给调用者 |
insert() |
插入新数据到ContentProvider |
updata() |
更新数据 |
delete() |
从ContentProvider中删除数据 |
getType() |
返回CntentProvider数据的MIME类型 |
eg:
- package com.example.mycontentprovider;
- import android.content.Context;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteOpenHelper;
- public class DBhelper extends SQLiteOpenHelper{
- public DBhelper(Context context) {
- super(context, "users.db", null, );
- }
- @Override
- public void onCreate(SQLiteDatabase db) {
- // TODO 初始化数据库
- db.execSQL("create table t_user(_id integer primary key,uname,upass,money)");
- db.execSQL("create table t_order(_id integer primary key,user_id,price,productname)");
- db.execSQL("insert into t_user(uname,upass,money) values('lisi','123',200)");
- db.execSQL("insert into t_user(uname,upass,money) values('zhangsi','1234',2000)");
- }
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- // TODO 数据库升级时执行该方法
- if(newVersion>oldVersion)
- {
- db.execSQL("drop table if exists t_user");
- db.execSQL("drop table if exists t_order");
- onCreate(db);
- }
- }
- }
DBhelper类 继承SQLiteOpenHelper
- package com.example.mycontentprovider;
- 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{
- /*
- * 这里有两个数据表t_user t_order
- * 给t_user Code标识1
- * 给t_order Code标识2
- * 假设当前只对表t_user操作
- *
- */
- //声明该ContentProvider的唯一标识
- public static final String AUTHORITY="com.xqx_mydatabase";
- //为该组件中可以被外界访问 数据库中的资源定义Code标识
- public static final int CODE_USER = ;
- public static final int CODE_ORDER = ;
- //定义访问资源的URI匹配器,使用该类生成被访问的资源的URI
- private static UriMatcher uriMather;
- private DBhelper dbhelper;
- static {
- uriMather = new UriMatcher(UriMatcher.NO_MATCH);
- //CODE_USER(1)对应的URI:content://com.xqx_mydatabase/user
- uriMather.addURI(AUTHORITY, "user", CODE_USER);
- //CODE_USER(2)对应的URI:content://com.xqx_mydatabase/order
- uriMather.addURI(AUTHORITY, "order", CODE_ORDER);
- }
- //删除返回删除成功记录的条数
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- // TODO Auto-generated method stub
- SQLiteDatabase db = dbhelper.getWritableDatabase();
- if(uriMather.match(uri)==CODE_USER)
- {
- //删除t_user表中的数据,返回删除记录的条数
- int num = db.delete("t_user", selection, selectionArgs);
- return num;
- }
- return ;
- }
- @Override
- public String getType(Uri uri) {
- // TODO Auto-generated method stub
- return null;
- }
- //插入记录
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- // TODO Auto-generated method stub
- SQLiteDatabase db = dbhelper.getWritableDatabase();
- if(uriMather.match(uri)==CODE_USER)
- {
- //得到插入记录的ID
- long id = db.insert("t_user", null, values);
- //返回新插入记录的URI
- return ContentUris.withAppendedId(uri, id);
- }
- return null;
- }
- //创建DBhelper对象
- @Override
- public boolean onCreate() {
- // TODO Auto-generated method stub
- dbhelper = new DBhelper(getContext());
- return false;
- }
- //查询,返回Cursor对象
- @Override
- public Cursor query(Uri uri, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) {
- // TODO Auto-generated method stub
- SQLiteDatabase db = dbhelper.getReadableDatabase();
- //得到uri对应的Code
- int code = uriMather.match(uri);
- Cursor cursor = null;
- switch (code) {
- //如果匹配CODE_USER 操作数据表t_user
- case CODE_USER:
- //查询数据表t_user
- cursor = db.query("t_user", projection, selection, selectionArgs, null, null, sortOrder);
- break;
- case CODE_ORDER:
- break;
- default:
- break;
- }
- return cursor;
- }
- //修改数据表中的数据,返回修改记录的条数
- @Override
- public int update(Uri uri, ContentValues values, String selection,
- String[] selectionArgs) {
- // TODO Auto-generated method stub
- SQLiteDatabase db = dbhelper.getWritableDatabase();
- if(uriMather.match(uri)==CODE_USER)
- {
- return db.update("t_user", values, selection, selectionArgs);
- }
- return ;
- }
- }
UserContentProvider.class 继承ContentProvider
(3)、在应用程序的AndroidManifest文件中注册Content Provider
- <!-- 注册 ContentProvider组件
- android:authorities:声明该组件的唯一标识
- android:permission:声明该组件的权限
- android:exported="true":声明该组件可以被外界应用访问
- -->
- <provider
- android:name="com.xqx.UserContentProvider"
- android:authorities="com.xqx.users"
- android:permission="com.xqx.READ_WRITE"
- android:exported="true"
- />
-----------------------------------------------------------------------------------------------
安卓开发_深入理解Content Provider的更多相关文章
- 安卓开发_深入理解Handler消息传递机制
一.概述 因为子线程的run()方法无法修改UI线程(主线程)的UI界面,所以Android引入了Handler消息传递机制,实现在新创建的线程中操作UI界面 二.消息类(Message) 消息类是存 ...
- 安卓开发_深入理解Activity和Fragment的关系
Fragment(碎片)是必须嵌入在 Activity(活动) 中使用的.Fragment的生命周期随着Activity的生命周期的变化而变化 一.首先让我们看下Activity和Fragment的生 ...
- 安卓开发_浅谈ListView(SimpleAdapter数组适配器)
安卓开发_浅谈ListView(ArrayAdapter数组适配器) 学习使用ListView组件和SimapleAdapter适配器实现一个带图标的ListView列表 总共3部分 一.MainAc ...
- 安卓开发_数据存储技术_sqlite
一.SQLite SQLite第一个Alpha版本诞生于2000年5月,它是一款轻量级数据库,它的设计目标是嵌入式的,占用资源非常的低,只需要几百K的内存就够了.SQLite已经被多种软件和产品使用 ...
- 安卓开发_浅谈ListView(自定义适配器)
ListView作为一个实际开发中使用率非常高的视图,一般的系统自带的适配器都无法满足开发中的需求,这时候就需要开发人员来自定义适配器使得ListView能够有一个不错的显示效果 有这样一个Demo ...
- 安卓开发_数据存储技术_SharedPreferences类
SharedPreferences类 供开发人员保存和获取基本数据类型的键值对. 该类主要用于基本类型,例如:booleans,ints,longs,strings.在应用程序结束后,数据仍旧会保存. ...
- 安卓开发_深入学习ViewPager控件
一.概述 ViewPager是android扩展包v4包(android.support.v4.view.ViewPager)中的类,这个类可以让用户左右切换当前的view. ViewPager特点: ...
- 安卓开发_浅谈Android动画(四)
Property动画 概念:属性动画,即通过改变对象属性的动画. 特点:属性动画真正改变了一个UI控件,包括其事件触发焦点的位置 一.重要的动画类及属性值: 1. ValueAnimator 基本属 ...
- 安卓开发_浅谈Fragment之ListFragment
ListFragment,即Fragment的一个子类,当我们用的一个Fragment只需要一个listview视图的时候使用 该类有几个特点: 1.ListFragment 本身具只有一个ListV ...
随机推荐
- Eclipse中java内存溢出
1.点击Window --->Preferences,如下图
- Liferay的一些应用领域
Liferay的用途是快速的部署内外站点,统一权限管理,开发Web热插拔插件,并不是所有系统都适合 不适合Liferay的一些应用领域: 1.独立认证.简单的系统,比如一些简单的增删改查:2.复杂业务 ...
- “大话架构”阿里架构师分享Java程序员需要突破的技术要点
一.源码分析 源码分析是一种临界知识,掌握了这种临界知识,能不变应万变,源码分析对于很多人来说很枯燥,生涩难懂. 源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心. 我认为是阅读源码的最核心 ...
- can only concatenate tuple (not "int") to tuple问题原因
#测试程序 import os from pydub import AudioSegment #已经确定, # enPath = "%s%s/%s"%(enDir,file,enf ...
- 使用Charles抓取APP之HTTPS请求
Charles是一款非常好用的抓包工具,通常使用它来进行APP开发抓包调试,尤其是HTTPS请求. 一.安装Charles 去官网(https://www.charlesproxy.com/)下载软件 ...
- webpack-loader是怎样炼成的
目录 啰嗦两句 loader 是干什么的 loader 的工具箱 --context loader 实战 啰嗦两句 学习这件事从学习动机上来看,可以分成两种情况:主动学习和被动学习.主动学习就是,某天 ...
- postgres 更新数据表
新增非空列: alter table t_test add column user_id integer; update t_test set user_id=0; alter table t_tes ...
- WinForm版图像编辑小程序(实现图像拖动、缩放、旋转、抠图)
闲暇之余,开发一个图片编辑小程序.程序主要特点就是可方便的对多个图像编辑,实现了一些基本的操作.本文主要介绍一下程序的功能.设计思路. 执行程序 下载地址: 百度网盘.https://pan.baid ...
- SQL 必知必会·笔记<11>创建高级联结
1. 使用表别名 SQL 除了可以对列名和计算字段使用别名,还允许给表名起别名.这样 做有两个主要理由: 缩短SQL 语句: 允许在一条SELECT 语句中多次使用相同的表. 使用表别名示例: SEL ...
- docker学习系列(四):数据持久化
需要搞清楚一个概念的是,docker的容器设计理念是可以即开即用,用完可以随意删除,而新建容器是根据镜像进行渲染,容器的修改是不会影响到镜像,但是有时候容器里面运行的产生的数据(如mysql)或者配置 ...