Android ContentProvider的介绍(很详细)
博客分类:
一、ContentProvider的概念
ContentProvider:为存储和获取数据提供统一的接口。可以在不同的应用程序之间共享数据。Android已经为常见的一些数据提供了默认的ContentProvider
1、ContentProvider使用表的形式来组织数据
无论数据的来源是什么,ContentProvider都会认为是一种表,然后把数据组织成表格
2、ContentProvider提供的方法
query:查询
insert:插入
update:更新
delete:删除
getType:得到数据类型
onCreate:创建数据时调用的回调函数
3、每个ContentProvider都有一个公共的URI,这个URI用于表示这个ContentProvider所提供的数据。Android所提供的ContentProvider都存放在android.provider包当中
二、ContentProvider的内部原理
自定义一个ContentProvider,来实现内部原理
步骤:
1、定义一个CONTENT_URI常量(里面的字符串必须是唯一)
Public static final Uri CONTENT_URI = Uri.parse("content://com.WangWeiDa.MyContentprovider");
如果有子表,URI为:
Public static final Uri CONTENT_URI = Uri.parse("content://com.WangWeiDa.MyContentProvider/users");
2、定义一个类,继承ContentProvider
Public class MyContentProvider extends ContentProvider
3、实现ContentProvider的所有方法(query、insert、update、delete、getType、onCreate)
package com.WangWeiDa.cp;
import java.util.HashMap;
import com.WangWeiDa.cp.MyContentProviderMetaData.UserTableMetaData;
import com.WangWeiDa.data.DatabaseHelp;
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;
public class MyContentProvider extends ContentProvider {
//访问表的所有列
public static final int INCOMING_USER_COLLECTION = 1;
//访问单独的列
public static final int INCOMING_USER_SINGLE = 2;
//操作URI的类
public static final UriMatcher uriMatcher;
//为UriMatcher添加自定义的URI
static{
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(MyContentProviderMetaData.AUTHORITIES,"/user",
INCOMING_USER_COLLECTION);
uriMatcher.addURI(MyContentProviderMetaData.AUTHORITIES,"/user/#",
INCOMING_USER_SINGLE);
}
private DatabaseHelp dh;
//为数据库表字段起别名
public static HashMap userProjectionMap;
static
{
userProjectionMap = new HashMap();
userProjectionMap.put(UserTableMetaData._ID,UserTableMetaData._ID);
userProjectionMap.put(UserTableMetaData.USER_NAME, UserTableMetaData.USER_NAME);
}
/**
* 删除表数据
*/
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
System.out.println("delete");
//得到一个可写的数据库
SQLiteDatabase db = dh.getWritableDatabase();
//执行删除,得到删除的行数
int count = db.delete(UserTableMetaData.TABLE_NAME, selection, selectionArgs);
return count;
}
/**
* 数据库访问类型
*/
@Override
public String getType(Uri uri) {
System.out.println("getType");
//根据用户请求,得到数据类型
switch (uriMatcher.match(uri)) {
case INCOMING_USER_COLLECTION:
return MyContentProviderMetaData.UserTableMetaData.CONTENT_TYPE;
case INCOMING_USER_SINGLE:
return MyContentProviderMetaData.UserTableMetaData.CONTENT_TYPE_ITEM;
default:
throw new IllegalArgumentException("UnKnown URI"+uri);
}
}
/**
* 插入数据
*/
@Override
public Uri insert(Uri uri, ContentValues values) {
//得到一个可写的数据库
SQLiteDatabase db = dh.getWritableDatabase();
//向指定的表插入数据,得到返回的Id
long rowId = db.insert(UserTableMetaData.TABLE_NAME, null, values);
if(rowId > 0){//判断插入是否执行成功
//如果添加成功,利用新添加的Id和
Uri insertedUserUri = ContentUris.withAppendedId(UserTableMetaData.CONTENT_URI, rowId);
//通知监听器,数据已经改变
getContext().getContentResolver().notifyChange(insertedUserUri, null);
return insertedUserUri;
}
return uri;
}
/**
* 创建ContentProvider时调用的回调函数
*/
@Override
public boolean onCreate() {
System.out.println("onCreate");
//得到数据库帮助类
dh = new DatabaseHelp(getContext(),MyContentProviderMetaData.DATABASE_NAME);
return false;
}
/**
* 查询数据库
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
//创建一个执行查询的Sqlite
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
//判断用户请求,查询所有还是单个
switch(uriMatcher.match(uri)){
case INCOMING_USER_COLLECTION:
//设置要查询的表名
qb.setTables(UserTableMetaData.TABLE_NAME);
//设置表字段的别名
qb.setProjectionMap(userProjectionMap);
break;
case INCOMING_USER_SINGLE:
qb.setTables(UserTableMetaData.TABLE_NAME);
qb.setProjectionMap(userProjectionMap);
//追加条件,getPathSegments()得到用户请求的Uri地址截取的数组,get(1)得到去掉地址中/以后的第二个元素
qb.appendWhere(UserTableMetaData._ID + "=" + uri.getPathSegments().get(1));
break;
}
//设置排序
String orderBy;
if(TextUtils.isEmpty(sortOrder)){
orderBy = UserTableMetaData.DEFAULT_SORT_ORDER;
}
else{
orderBy = sortOrder;
}
//得到一个可读的数据库
SQLiteDatabase db = dh.getReadableDatabase();
//执行查询,把输入传入
Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);
//设置监听
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
/**
* 更新数据库
*/
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
System.out.println("update");
//得到一个可写的数据库
SQLiteDatabase db = dh.getWritableDatabase();
//执行更新语句,得到更新的条数
int count = db.update(UserTableMetaData.TABLE_NAME, values, selection, selectionArgs);
return count;
}
}
4、在AndroidMinifest.xml中进行声明
android:name=".cp.MyContentProvider"
android:authorities="com.WangWeiDa.cp.MyContentProvider"
/>
**为ContentProvider提供一个常量类MyContentProviderMetaData.java
package com.WangWeiDa.cp;
import android.net.Uri;
import android.provider.BaseColumns;
public class MyContentProviderMetaData {
//URI的指定,此处的字符串必须和声明的authorities一致
public static final String AUTHORITIES = "com.wangweida.cp.MyContentProvider";
//数据库名称
public static final String DATABASE_NAME = "myContentProvider.db";
//数据库的版本
public static final int DATABASE_VERSION = 1;
//表名
public static final String USERS_TABLE_NAME = "user";
public static final class UserTableMetaData implements BaseColumns{
//表名
public static final String TABLE_NAME = "user";
//访问该ContentProvider的URI
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITIES + "/user");
//该ContentProvider所返回的数据类型的定义
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.myprovider.user";
public static final String CONTENT_TYPE_ITEM = "vnd.android.cursor.item/vnd.myprovider.user";
//列名
public static final String USER_NAME = "name";
//默认的排序方法
public static final String DEFAULT_SORT_ORDER = "_id desc";
}
}
Android ContentProvider的介绍(很详细)的更多相关文章
- 很详细、很移动的Linux makefile教程:介绍,总述,书写规则,书写命令,使用变量,使用条件推断,使用函数,Make 的运行,隐含规则 使用make更新函数库文件 后序
很详细.很移动的Linux makefile 教程 内容如下: Makefile 介绍 Makefile 总述 书写规则 书写命令 使用变量 使用条件推断 使用函数 make 的运行 隐含规则 使用m ...
- 我的Android第三章:Android的组件介绍
小编摘录了Android文档介绍Android四大组件的基本内容,感觉文档的内容写的很详细所以小编将它写入了博客 Android 使用Java语言开发.Android SDK 工具编译代码-以及任意数 ...
- GitHub上排名前100的Android开源库介绍(来自github)
本项目主要对目前 GitHub 上排名前 100 的 Android 开源库进行简单的介绍,至于排名完全是根据 GitHub 搜索 Java 语言选择 (Best Match) 得到的结果,然后过滤了 ...
- Android发展简单介绍
Android一词的本义指“机器人”,同一时候也是Google于2007年11月5日宣布的基于Linux平台的开源手机操作系统的名称,该平台由操作系统.中间件.用户界面和应用软件组成,号称是首个为移动 ...
- Android 环境搭建与Android SDK目录介绍
Android SDK下载和安装 本地已有合适版本Android SDK,则无需再下载,或者可以使用SDK Manager更新SDK: 没有SDK,则需要下载. 这里说一下使用SDK Manager下 ...
- 很详细的SpringBoot整合UEditor教程
很详细的SpringBoot整合UEditor教程 2017年04月10日 20:27:21 小宝2333 阅读数:21529 版权声明:本文为博主原创文章,未经博主允许不得转载. https: ...
- Android Debuggerd 简要介绍和源码分析(转载)
转载: http://dylangao.com/2014/05/16/android-debuggerd-%E7%AE%80%E8%A6%81%E4%BB%8B%E7%BB%8D%E5%92%8C%E ...
- GitHub上排名前100的Android开源库介绍
GitHub上排名前100的Android开源库介绍 文章来源: http://www.open-open.com/news/view/1587067#6734290-qzone-1-31660-bf ...
- 细数 Windows Phone 灭亡的七宗罪(过程很详细,评论很精彩,但主要还是因为太慢了,生态跟不上,太贪了,厂商不愿意推广)
曾梦想仗剑走天涯,看一看世界的繁华 年少的心有些轻狂,如今你四海为家 曾让你心疼的姑娘,如今已悄然无踪影 犹记得上大学攒钱买了第一台智能手机Lumia 520时,下载的第一首歌曲<曾经的你> ...
随机推荐
- windows phone开发必备工具翔
1.图标设计 http://www.flaticon.com/ http://www.iconfont.cn/ 2.界面设计: 2.1.behance.com 2.2.dribbble.com ...
- Block Formatting Contexts (块级格式化上下文) 详解
最近在学习BootStrap框架,发现里面清除浮动的类 .clearfix 跟平时自己用的不太一样.它的样式是这样的: .clearfix:before { content: " ...
- Kotlin when 流程判断
如果学过C或者java C#等语言. 一定熟悉SWITCH这个流程判断 但是在kotlin中却没有这个.而是 使用了When来代替. 当什么时候. 下面我觉一个简单的例子: import java.u ...
- [agc008f] Black Radius 树形dp
Description 给你一棵有NN个节点的树,节点编号为11到NN,所有边的长度都为11 "全"对某些节点情有独钟,这些他喜欢的节点的信息会以一个长度为NN的字符串ss ...
- URL编码以及GET和POST提交乱码解决方案
get方式时参数是作为url一部分传输的.而对于url是有规范的,汉字超出了规范的范围. post方式不需要加编码是错误的.post时也必须传送符合服务器规范的编码.如果错误,服务器收到的内容也不会正 ...
- angluarJs与后台交互小案例
.myService.html: <!DOCTYPE HTML> <html ng-app="app"> <head> <title> ...
- 13. js延迟加载的方式有哪些
JS延迟加载,也就是等页面加载完成之后再加载 JavaScript 文件. JS延迟加载有助于提高页面加载速度. 一般有以下几种方式: 1)defer 属性 <script src=&q ...
- sublime text3 添加新片段
1.tools->developer->new snippet 要介绍一下snippet四个组成部分: content:其中必须包含<![CDATA[…]]>,否则无法工作, ...
- Chrome浏览器如何完美实现滚动截图技巧
一.前言 我们平时在浏览网页时,想把碰到好的网页内容或者文章截屏保存,但是网页的长度常常会超出屏幕高度,一般的截屏功能只能截取显示在屏幕上的内容,那我们该如何方便快捷截取全部内容?今天就分享一个如何利 ...
- Python web前端 01 HTML常用标签
Python web前端 01 HTML常用标签 一.HTML创建项目 file ---->new project -----> 输入项目名------>创建文件夹 new dicr ...