ContentResolver与ContentProvider的搭配使用
简介
Android中, ContentResolver是通过Uri来获取对应数据的数据, 而提供数据的,通常就是ContentProvider。ContentProvider可以作为一个公共的数据源,为多个app提供数据的增删改查。
以下例子先建立一个ContentProvider, 在其内部简历数据库,然后让ContentResolver来查询数据。
先看例子的示意图:
1、插入数据和查询数据
查看数据库的两列数据:1、单词; 2、单词描述, 这里直插入了单词,暂未插入描述
2、修改数据
修改以b结尾的单词的描述, 这里把描述改为了222
3、删除数据
删除以a开头的所有单词
4、数据库表(用Sqlite Expert工具查看)
主要有三列: id, word, describe
Sqlite Expert工具破解版下载地址: https://download.csdn.net/download/qq475703980/11833576
一、ContentProvider的创建
1、自定义ContentProvider
继承ContentProvider后,需要实现六个抽象方法:
public class DictProvider extends ContentProvider {@Overridepublic boolean onCreate() {//只会在ContentProvider启动时调用一次return true;}@Nullable@Overridepublic Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {return null;}@Nullable@Overridepublic String getType(@NonNull Uri uri) {return null;}@Nullable@Overridepublic Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {return null;}@Overridepublic int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {return 0;}@Overridepublic int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {return 0;}
}
下面就介绍具体这几个方法如何使用。
Uri简介
Uri: 统一资源标识符(Uniform Resource Identifier,URI)。每个资源都应该有唯一一个符号来标识,就像每一个网址都有唯一可识别的地址一样。
我们先看当前博客的网址:https://blog.csdn.net/qq475703980
这个地址可以分为三部分:
- 1、https:// :这个表示协议,只能通过https协议来访问,这部分是固定的
- 2、blog.csdn.net : 域名部分,这是CSDN的网址
- 3、qq475703980 :网址资源部分,这里就指向了CSDN的qq475703980这个博客
在android中,我们provider的uri地址通常格式为:“content://com.op.billy.dict.provider/dict”, 其中“content://”是固定的协议,而"com.op.billy.dict.provider"是一个provider的唯一标识,这个也需要在manifest中注册 "dict"标识这个provider里面的某个资源路径。
在Manifest中注册ContentProvider
<providerandroid:name=".DictProvider"android:authorities="com.op.billy.dict.provider"android:exported="true" />
authorities是用来一个Provider的唯一标识,就类似于网站的网址一样,每个网站的网址是固定的,不会两家公司的网址都是相同的,所以在Android中,为了防止两个应用的authorities相同, 如果后安装的apk的authorities和已安装的apk的authorities相同,则新的apk无法安装成功。因为apk安装时,会首先解析apk的manifest,然后将其中的四大组件注册到系统服务中,进行统一管理,先安装的apk自然就先注册了。
1、onCreate方法
onCreate方法只会在provider启动时调用一次,启动后不再回调此方法,通常用来做一些初始化操作及拿到DatabaseHelper的引用:
@Override
public boolean onCreate() {Log.d(TAG, "onCreate");//初始化操作dict_db这个数据库的DatabaseHelper,自定义的DictDatabaseHelper主要是用来创建了数据库dict_dbmDbHelper = new DictDatabaseHelper(getContext(), "dict_db", null, 1);return true;
}
2、getType方法
getType主要是用来返回数据mimetype类型:
@Override
public String getType(@NonNull Uri uri) {//返回指定Uri参数对应的数据的MIME TYPE 类型switch (mUriMatcher.match(uri)) {case CODE_DICT://返回的cursor是单项记录,即只查询了一行return "vnd.android.cursor.item/op.dict";case CODE_DESCRIBE:return "vnd.android.cursor.item/op.describe";case CODE_DICTS://返回的cursor是多想记录,查询了多行return "vnd.android.cursor.dir/op.dicts";case CODE_DESCRIBES:return "vnd.android.cursor.dir/op.describes";}return null;
}
这个方法的意义是返回某种mime类型,确定了类型以后,去查询数据库的时候就不会再进行判断了, 效率更高;如果这里返回任意字符串也是可以的,只是这个方法就是去了作用,查询数据库的效率会降低。
这里根据传递进来的uri,返回不同的mime类型, 其中"vnd.android.cursor.item/op.dict"表示cursor操作单行记录录,"vnd.android.cursor.dir/op.dicts"表示 cursor操作多行记录。
其中前半段"vnd.android.cursor.dir"是Android系统定义的mime类型,是系统可以识别的,“vnd.android.cursor.dir” 表示cursor可以操作的是多行数据; 后半段"/op.dicts"使我们自定义的字段,表示具体的我们的provider内部使用的一种类型。
系统定义了很多mime类型,我们在manifest清单中设置四大组件有时也会使用到, 具体的mime类型介绍可以参考博客: https://blog.csdn.net/harvic880925/article/details/44620851
3、insert方法
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {SQLiteDatabase db = mDbHelper.getWritableDatabase();switch (mUriMatcher.match(uri)) {case CODE_DICT:long rowId = db.insert(DictDatabaseHelper.TABLE_DICT, DictDatabaseHelper.COLUMN_WORD, values);if(rowId > 0) {Log.d(TAG, "rowId = "+rowId);Uri wordUri = ContentUris.withAppendedId(uri, rowId);return wordUri;//返回这个插入单词的位置notifyDataChanged(uri);}}return null;
}
这里主要介绍参数ContentValues, ContentValue主要通过key ,value来保存值,其key应该与数据库表中的列名相同, value就是这一列需要插入的值, 如果key与列名不对应,会报错。
4、query方法
执行数据库的查询方法,
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {Log.d(TAG, "query");SQLiteDatabase db = mDbHelper.getReadableDatabase();switch (mUriMatcher.match(uri)) {case CODE_DICT:Log.d(TAG, "CODE_DICT");//执行查询return db.query(DictDatabaseHelper.TABLE_DICT, projection, selection, selectionArgs, null, null, sortOrder);default:}return null;
}
它的参数分别为:
- Uri uri: 根据传递过来的uri, 我们去查询数据库中不同的表,uri和表的对应关系,使我们自己定义的;
- String[] projection: 要查询的列的名字 组成的数组,如果有数据,返回的cursor数据也会按照这个projection传递进来的列名的顺序返回对应的数据;
- String selection: 筛选条件,如果需要对数据进行某种筛选
- String[] selectionArgs: 如果上一条 selection是一个完整的sql筛选语句,则此参数可以为null, 如果不是一个完整的selection语句,其具体参数用占位符?替代了,那么这个参数依次传递的数据替代前一句的占位符?;
- String sortOrder:数据库的排序语句, 可以为null;
剩下的delete和update方法就和上述方法类似了,传入的参数已经介绍过了, 下面看ContentResolver如何来操作我们的Provider,使其可以增删改查数据库的数据。
二、使用ContentResolver操作ContentProvider的数据
只要有Context上下文,我们就可以通过它来获取ContentResolver
ContentResolver mResolver = context.getContentResolver();
1、使用ContentResolver插入数据
private final String AUTHORITY = "com.op.billy.dict.provider";
private final String DICT_PATH = "dict";
private final String COLUMN_NAME_DICT = "word";
private final String COLUMN_NAME_DESCRIBE = "describe";
private final Uri URI_DICT = Uri.parse("content://" + AUTHORITY + File.separatorChar + DICT_PATH);
...
ContentValues cv = new ContentValues();
cv.put(COLUMN_NAME_DICT, input);//根据列名插入数据
mResolver.insert(URI_DICT, cv);
使用ContentResolver修改更新数据
String input_describe = mEditText.getText().toString();cv.put(COLUMN_NAME_DESCRIBE,input_describe);String where = "word like ?";//"word like '%b'";//如果使用?做占位符,那么下面再传入模糊查询的字符串时,不在需要单引号String[] selectionArgs_update = {"%b"};mResolver.update(URI_DICT_DESCRIBE, cv, where, selectionArgs_update);
注意坑点, 这里"word like ‘%b’"表示筛选的sql语句,指筛选word这一列中以b结尾的单词,注意如果直接在where语句中这么写, %b 要加单引号, 如果使用下一种占位符的方式传递,则不需要单引号:
String where = "word like ?"String[] selectionArgs_update = {"%b"};
###使用ContentResolver修改获取数据
//projection :想要查询的列的的集合(传入列名),可以使单列或多列
String selection = "word like '%b'"; //查询的选择条件, 具体值用占位符 ? 表示//查询条件中的具体值,代替上述的占位符, a%表示以a开头, %b表示以b结尾, %c%表示包含c
String[] selectionArgs = {" a% ", " %b "};//查询单词以a开头的,描述以b结尾的 行
Cursor cursor = mResolver.query(URI_DICT, mProjections, null, null, null);
if(cursor != null &&cursor.getCount() > 0) {
int count = cursor.getCount();
String result = "result count= " + count +"\n";
while(cursor.moveToNext()) {result += cursor.getString(0) +", " +cursor.getString(1)+"\n";
}
mTvShow.setText(result);
##demo 源码
以上就是关于ContentProvider以及ContentResolver的使用, demo的源码地址如下,环宇查看:
https://github.com/Billyshi/BillyApplication.git
https://github.com/Billyshi/BillyProvider.git
ContentResolver与ContentProvider的搭配使用相关推荐
- android的contentResolver,contentProvider简介(附带个获取手机联系人及头像实例)
介绍 android中有个ContentProvider(内容提供者)还有个ContentResolver(内容解析者) 简单来说,contentProvider就是将自己app的数据库共享,使得其他 ...
- Linux内核很吊之 module_init解析 (下)
Linux内核很吊之 module_init解析 (下) 转载 2017年01月23日 13:58:21 标签: 95 编辑 删除 转自: http://blog.csdn.net/richard_l ...
- ContentProvider与ContentResolver使用
例如以下内容为从网络转载: 使用ContentProvider共享数据: 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就能够向其它应用共享其数据.虽然使用其它方 ...
- Android ContentProvider和ContentResolver实例
ContentResolver和ContentProvider通过相同的URI联系,实现数据共享.我重写了public class MyAdapter extends BaseAdapter,putD ...
- ContentProvider之ContentResolver
(一).SQLiteDatabase和SQLiteOpenHelper的封装: (二).ListView分页显示数据: 目标:能完成以下功能--访问本地网址,实现异步加载数据,解析json数据,分页显 ...
- android中contentProvider及ContentResolver
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程 这个技术是解决应用之间的一个调用,如常见的应用间数据库查询,内容提供者暴露接口,内容解析器Conten ...
- Android四大组件之ContentProvider 全面解析,ContentResolver源码解析如何调用其它APP的ContentProvider
今天来总结下Android中的ContentProvider(以下简称CP),具体代码请见https://github.com/Mangosir/ContentProviderReview/tree/ ...
- contentProvider的使用总结
一.使用ContentProvider(内容提供者)共享数据 ContentProvider在android中的作用是对外共享数据,也就是说你可以通过ContentProvider把应用中的数据共享给 ...
- Android ContentProvider和getContentResolver
安卓系统中的数据库SqlLite操作和java中mysql的数据库操作很不一样,造成这样的原因是因为在安卓中数据库是属于进程的不存在数据库客户端,也不存在数据库服务器. 关于SqlLite数据库的文章 ...
最新文章
- poi 合并单元格_POI数据获取脚本分享
- mysql sleep连接过多的问题解决
- 个人密码安全策略 [转载]
- java核心标签库,16.JSTL标签库(我的JavaEE笔记)
- 【Linux网络编程】IP 数据报格式详解
- java for循环 嵌套for循环-标签使用
- 升级到vCenter Server 6.5的最佳实践(2147686)
- IT职场人生系列之十五:语言与技术II
- 机器学习基础:评价指标(Machine Learning Fundamentals: Evaluation Metrics)
- HTML:雪碧图、高度塌陷和序号选择器
- 如何使用GetParent来得到父对话框的指针
- 7建站php_2019最受欢迎的企业网站CMS建站系统排行榜
- 矩形窗函数rect()和辛格函数sinc()是一组傅里叶变换对相关公式证明
- 通过搜狗搜索爬取微信公众号文章,小程序版可体验
- Rplidar A1/A2使用及Hector_SLAM建图
- Java简繁体汉字转化
- MPC-HC 播放器设置
- windows黑客编程系列(六):进程遍历之查询系统是否运行杀软
- 11,SFDC 管理员篇 - 报表和数据的可视化
- 八位硕博大佬的百度之旅~
热门文章
- 内核aio_浅析Linux Native AIO的实现
- 天道有轮回!网络诈骗之国尼日利亚政府网站被挂钓鱼网站
- Mysql中父子查询 单表根据id查询parentId
- android%3cspan,新时代赌城全部网址
- 百度糯米iOS客户端登录BUG
- AE 新建合成组 适合电脑上的设置
- 独家|【云+端】战略发布,助力快速上云
- ajaxfileupload 返回值_ajaxfileupload返回文件名中文乱码
- Echarts表格数据转换工具
- android opencv 数码变焦,Android开发(53) 摄像头自动对焦。在OpenCV图像识别中连续拍照时自动对焦和拍照。......