




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】还没弄懂四大组件?带你全面解析ContentProvider篇
喜欢的小伙伴欢迎关注,我会定期分享Android知识点及解析,还会不断更新的BATJ面试专题,欢迎大家前来探讨交流,如有好的文章也欢迎投稿。1.什么是ContentProviderContentProvider,是自身APP开放给第三方APP的,用于访问自身数据库数据的接口。第三方APP可以通过该接口,对指定的数据进行增删改查。那么如何定义自身的ContentProvider接口呢?在回答问题之前,先来关注一下Uri。2.什么是Uri原因在于,uri是ContentProvider解析外部请求(或者说是,第三方访问自身数据库)的关键参数。Uri的字符串格式如下content://package/table/idcontent://package/table/id例如content://com.breakloop.sqlitehelperdemo/hero/1content://com.breakloop.sqlitehelperdemo/hero/1从上方Uri示例中,可以获取到以下信息。第三方APP想要访问com.breakloop.sqlitehelperdemo的数据库。至于哪个,由contentProvider内部映射指定。访问表hero。至于表名是不是真为hero,也由contentProvider说了算。访问id为1的数据。至于是不是id代表的具体含义,解释权也归contentProvider。那么,第三方APP将Uri传入后,ContentProvider如何将其map为具体的数据库操作呢?这便有了UriMatcher工具类的引入。3.UriMatcher该工具类,可以将Uri映射为int类型的行为代码。行为代码,可以看做是ContentProvider自定义的枚举类型。而不同的行为代码,绑定不同的数据库操作。我们先来看一下,Uri与行为代码的映射关系
public
final
static
String
AUTHORITY="com.breakloop.contentproviderdemo1";
public
final
static
int
BY_NAME=1;
public
final
static
int
BY_AGE=2;
public
final
static
int
BY_SEX=3;
public
final
static
int
BY_NONE=0;
public
final
static
String
PATH_BY_NAME=DBConst.TABLE_PERSON+"/ByName/*";
public
final
static
String
PATH_BY_AGE=DBConst.TABLE_PERSON+"/ByAge/#";
public
final
static
String
PATH_BY_SEX=DBConst.TABLE_PERSON+"/BySex/*";
}static
{
matcher=new
UriMatcher(UriMatcher.NO_MATCH);
matcher.addURI(MatcherConst.AUTHORITY,MatcherConst.PATH_BY_NAME,MatcherConst.BY_NAME);
matcher.addURI(MatcherConst.AUTHORITY,MatcherConst.PATH_BY_AGE,MatcherConst.BY_AGE);
matcher.addURI(MatcherConst.AUTHORITY,MatcherConst.PATH_BY_SEX,MatcherConst.BY_SEX);
matcher.addURI(MatcherConst.AUTHORITY,DBConst.TABLE_PERSON,MatcherConst.BY_NONE);
}在上面的示例中,UriMatch绑定了四个Uri,并将各个Uri映射为四个行为代码。其中,用到了转义符。#代表任意数字,*代表任意字母。那么如何将行为代码映射为具体的数据库操作呢?,换句话说,在哪儿使用UriMatcher呢?当然是ContentProvider中!!!在ContentProvider中的增删改查方法中,完成操作映射。我们来看一下,ContentProvider的创建。4.ContentProvider的创建先用AndroidStudio创建一个ContentProvider.创建过程中,需要提供AUTHORITY,ContentProvider生成后,AndroidStudio将自动帮助ContentProvider在Manifest中进行注册。接下来,我们看看ContentProvider的结构。5.ContentProvider的结构import
android.content.ContentProvider;import
android.content.ContentValues;import
android.content.UriMatcher;import
android.database.Cursor;import
.Uri;public
class
MyContentProvider
extends
ContentProvider
{
public
MyContentProvider()
{
}
@Override
public
int
delete(Uri
uri,
String
selection,
String[]
selectionArgs)
{
//
Implement
this
to
handle
requests
to
delete
one
or
more
rows.
throw
new
UnsupportedOperationException("Not
yet
implemented");
}
@Override
public
String
getType(Uri
uri)
{
//
TODO:
Implement
this
to
handle
requests
for
the
MIME
type
of
the
data
//
at
the
given
URI.
throw
new
UnsupportedOperationException("Not
yet
implemented");
}
@Override
public
Uri
insert(Uri
uri,
ContentValues
values)
{
//
TODO:
Implement
this
to
handle
requests
to
insert
a
new
row.
throw
new
UnsupportedOperationException("Not
yet
implemented");
}
@Override
public
boolean
onCreate()
{
//
TODO:
Implement
this
to
initialize
your
content
provider
on
startup.
return
false;
}
@Override
public
Cursor
query(Uri
uri,
String[]
projection,
String
selection,
String[]
selectionArgs,
String
sortOrder)
{
//
TODO:
Implement
this
to
handle
query
requests
from
clients.
throw
new
UnsupportedOperationException("Not
yet
implemented");
}
@Override
public
int
update(Uri
uri,
ContentValues
values,
String
selection,
String[]
selectionArgs)
{
//
TODO:
Implement
this
to
handle
requests
to
update
one
or
more
rows.
throw
new
UnsupportedOperationException("Not
yet
implemented");
}
}一共七个方法。包括一个构造方法,四个数据库方法(增删改查),一个初始化方法(onCreate),还有一个getType。关于getType,我们之后解释。关于构造方法,没什么可解释的。关于初始化方法,当返回true时,表明初始化成功,否则,失败。由于我们要对数据库进行操作,因此,需要获取sqlite数据库对象。public
boolean
onCreate()
{
helper=new
mySqliteHelper(getContext(),DBConst.DB_NAME,null,1);
return
true;
}关于数据库方法,我们看到传参中存在Uri,因此,这里需要用到UirMatcher了。我们将刚才的UriMatcher代码段,加入MyContentProvider.这样,我们就可以在各个数据库方法中,解析Uri了。同时,由于sqlite数据库对象的存在,进而可以对数据库进行相应操作。6.行为代码Mapping数据库操作我们先看一下最简单的插入操作。
public
Uri
insert(Uri
uri,
ContentValues
values)
{
Uri
returnUri=null;
SQLiteDatabase
db=helper.getWritableDatabase();
switch
(matcher.match(uri)){
case
MatcherConst.BY_NONE:
long
recordID=db.insert(DBConst.TABLE_PERSON,null,values);
returnUri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/"+recordID);
break;
default:
break;
}
return
returnUri;
}再来看一下稍微复杂的查询。
public
Cursor
query(Uri
uri,
String[]
projection,
String
selection,
String[]
selectionArgs,
String
sortOrder)
{
Cursor
cursor=null;
SQLiteDatabase
db=helper.getReadableDatabase();
switch
(matcher.match(uri)){
case
MatcherConst.BY_NONE:
cursor=db.query(DBConst.TABLE_PERSON,projection,selection,selectionArgs,null,null,sortOrder);
break;
case
MatcherConst.BY_AGE:
cursor=db.query(DBConst.TABLE_PERSON,projection,DBConst.COLUMN_AGE+"=?",new
String[]{uri.getPathSegments().get(2)},null,null,sortOrder);
break;
case
MatcherConst.BY_SEX:
cursor=db.query(DBConst.TABLE_PERSON,projection,DBConst.COLUMN_SEX+"=?",new
String[]{uri.getPathSegments().get(2)},null,null,sortOrder);
break;
case
MatcherConst.BY_NAME:
cursor=db.query(DBConst.TABLE_PERSON,projection,DBConst.COLUMN_NAME+"=?",new
String[]{uri.getPathSegments().get(2)},null,null,sortOrder);
break;
default:
break;
}
return
cursor;
}这里需要注意的是,如何取Uri中的传入数据。使用的获取方法是uri.getPathSegments().get(index)。该方法获取的是AUTHORITY后面的String部分。然后,以”/”为分隔符,生成String[]。接着是更新操作。
@Override
public
int
update(Uri
uri,
ContentValues
values,
String
selection,
String[]
selectionArgs)
{
int
recordID=0;
SQLiteDatabase
db=helper.getWritableDatabase();
switch
(matcher.match(uri)){
case
MatcherConst.BY_NONE:
recordID=db.update(DBConst.TABLE_PERSON,values,null,null);
break;
case
MatcherConst.BY_AGE:
recordID=db.update(DBConst.TABLE_PERSON,values,DBConst.COLUMN_AGE+"=?",new
String[]{uri.getPathSegments().get(2)});
break;
case
MatcherConst.BY_SEX:
recordID=db.update(DBConst.TABLE_PERSON,values,DBConst.COLUMN_SEX+"=?",new
String[]{uri.getPathSegments().get(2)});
break;
case
MatcherConst.BY_NAME:
recordID=db.update(DBConst.TABLE_PERSON,values,DBConst.COLUMN_NAME+"=?",new
String[]{uri.getPathSegments().get(2)});
break;
default:
break;
}
return
recordID;
}还有删除。
public
int
delete(Uri
uri,
String
selection,
String[]
selectionArgs)
{
int
recordID=0;
SQLiteDatabase
db=helper.getWritableDatabase();
switch
(matcher.match(uri)){
case
MatcherConst.BY_NONE:
recordID=db.delete(DBConst.TABLE_PERSON,null,null);
break;
case
MatcherConst.BY_AGE:
recordID=db.delete(DBConst.TABLE_PERSON,DBConst.COLUMN_AGE+"=?",new
String[]{uri.getPathSegments().get(2)});
break;
case
MatcherConst.BY_SEX:
recordID=db.delete(DBConst.TABLE_PERSON,DBConst.COLUMN_SEX+"=?",new
String[]{uri.getPathSegments().get(2)});
break;
case
MatcherConst.BY_NAME:
recordID=db.delete(DBConst.TABLE_PERSON,DBConst.COLUMN_NAME+"=?",new
String[]{uri.getPathSegments().get(2)});
break;
default:
break;
}
return
recordID;
}那么,第三方如何调用ContentProvider呢?7.ContentProvider的使用这里,我们新建一个工程contentproviderdemo2,在必要的位置使用方法publicContentResolvergetContentResolver()publicContentResolvergetContentResolver()获取ContentProvider实例,之后便可传入Uri,调用数据库相关方法了。例如,我们插入四条记录。
Uri
returnUri=null;
ContentResolver
resolver=getContentResolver();
Uri
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON);
ContentValues
values=new
ContentValues();
values.put(DBConst.COLUMN_NAME,"A");
values.put(DBConst.COLUMN_AGE,10);
values.put(DBConst.COLUMN_SEX,"Male");
returnUri=resolver.insert(uri,values);
if(returnUri!=null)
Log.i(TAG,
"return
Uri
=
"+returnUri.toString());
values.put(DBConst.COLUMN_NAME,"B");
values.put(DBConst.COLUMN_AGE,11);
values.put(DBConst.COLUMN_SEX,"Male");
returnUri=resolver.insert(uri,values);
if(returnUri!=null)
Log.i(TAG,
"return
Uri
=
"+returnUri.toString());
values.put(DBConst.COLUMN_NAME,"C");
values.put(DBConst.COLUMN_AGE,12);
values.put(DBConst.COLUMN_SEX,"Female");
returnUri=resolver.insert(uri,values);
if(returnUri!=null)
Log.i(TAG,
"return
Uri
=
"+returnUri.toString());
values.put(DBConst.COLUMN_NAME,"D");
values.put(DBConst.COLUMN_AGE,13);
values.put(DBConst.COLUMN_SEX,"Female");
returnUri=resolver.insert(uri,values);
if(returnUri!=null)
Log.i(TAG,
"return
Uri
=
"+returnUri.toString());我们看一下输出结果。I/com.breakloop.contentproviderdemo2.MainActivity:
return
Uri
=
content://com.breakloop.contentproviderdemo1/PERSON/1I/com.breakloop.contentproviderdemo2.MainActivity:
return
Uri
=
content://com.breakloop.contentproviderdemo1/PERSON/2I/com.breakloop.contentproviderdemo2.MainActivity:
return
Uri
=
content://com.breakloop.contentproviderdemo1/PERSON/3I/com.breakloop.contentproviderdemo2.MainActivity:
return
Uri
=
content://com.breakloop.contentproviderdemo1/PERSON/4既然,写入成功,那我们查询一下。
public
void
selectRecord(){
Uri
uri;
String
name="A";
int
age=11;
String
sex="Male";
Log.i(TAG,
"Select
by
Name");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/ByName/"+name);
selectRecord(uri);
Log.i(TAG,
"Select
by
Age");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/ByAge/"+age);
selectRecord(uri);
Log.i(TAG,
"Select
by
Sex");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/BySex/"+sex);
selectRecord(uri);
Log.i(TAG,
"Select
All");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON);
selectRecord(uri);
}
private
void
selectRecord(Uri
uri){
Cursor
cursor;
cursor=resolver.query(uri,new
String[]{DBConst.COLUMN_AGE,
DBConst.COLUMN_NAME,
DBConst.COLUMN_SEX},null,null,null);
if(cursor!=null){
while(cursor.moveToNext()){
Log.i(TAG,
"name
=
"+cursor.getString(1)+
"
age
=
"+cursor.getInt(0)
+"
"+cursor.getString(2));
}
}
}输出结果如下I/com.breakloop.contentproviderdemo2.MainActivity:
Select
by
Name
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
A
age
=
10
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
Select
by
Age
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
B
age
=
11
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
Select
by
Sex
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
A
age
=
10
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
B
age
=
11
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
Select
All
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
A
age
=
10
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
B
age
=
11
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
C
age
=
12
Female
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
D
age
=
13
Female我们再来更新一下。
public
void
updateRecord(){
Uri
uri;
String
name="A";
int
age=11;
String
sex="Female";
ContentValues
values=new
ContentValues();
Log.i(TAG,
"Update
by
Name");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/ByName/"+name);
values.put(DBConst.COLUMN_NAME,name+name);
update(uri,values);
Log.i(TAG,
"Update
by
Age");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/ByAge/"+age);
values.clear();
values.put(DBConst.COLUMN_AGE,14);
update(uri,values);
Log.i(TAG,
"Update
by
Sex");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/BySex/"+sex);
values.clear();
values.put(DBConst.COLUMN_AGE,15);
update(uri,values);
Log.i(TAG,
"Update
All");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON);
values.put(DBConst.COLUMN_SEX,"Male");
update(uri,values);
Log.i(TAG,
"Select
All");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON);
selectRecord(uri);
}
private
void
update(Uri
uri,ContentValues
values){
int
count;
count=resolver.update(uri,values,null,null);
Log.i(TAG,
"update
"+count+"
record");
}结果如下I/com.breakloop.contentproviderdemo2.MainActivity:
Update
by
Name
I/com.breakloop.contentproviderdemo2.MainActivity:
update
1
record
I/com.breakloop.contentproviderdemo2.MainActivity:
Update
by
Age
I/com.breakloop.contentproviderdemo2.MainActivity:
update
1
record
I/com.breakloop.contentproviderdemo2.MainActivity:
Update
by
Sex
I/com.breakloop.contentproviderdemo2.MainActivity:
update
2
record
I/com.breakloop.contentproviderdemo2.MainActivity:
Update
All
I/com.breakloop.contentproviderdemo2.MainActivity:
update
4
record
I/com.breakloop.contentproviderdemo2.MainActivity:
Select
All
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
AA
age
=
15
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
B
age
=
15
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
C
age
=
15
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
D
age
=
15
Male都不要了,删除!(这里是对更新前的数据库进行的操作)
public
void
deleteRecord(){
Uri
uri;
String
name="A";
int
age=11;
String
sex="Female";
Log.i(TAG,
"Delete
by
Name");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/ByName/"+name);
delete(uri);
Log.i(TAG,
"Select
All");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON);
selectRecord(uri);
Log.i(TAG,
"Delete
by
Age");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/ByAge/"+age);
delete(uri);
Log.i(TAG,
"Select
All");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON);
selectRecord(uri);
Log.i(TAG,
"Delete
by
Sex");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON+"/BySex/"+sex);
delete(uri);
Log.i(TAG,
"Select
All");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON);
selectRecord(uri);
Log.i(TAG,
"Delete
All");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON);
delete(uri);
Log.i(TAG,
"Select
All");
uri=Uri.parse("content://"+MatcherConst.AUTHORITY+"/"+DBConst.TABLE_PERSON);
selectRecord(uri);
}
private
void
delete(Uri
uri){
int
count;
count=resolver.delete(uri,null,null);
Log.i(TAG,
"delete
"+count+"
record");
}结果如下I/com.breakloop.contentproviderdemo2.MainActivity:
delete
1
record
I/com.breakloop.contentproviderdemo2.MainActivity:
Select
All
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
B
age
=
11
Male
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
C
age
=
12
Female
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
D
age
=
13
Female
I/com.breakloop.contentproviderdemo2.MainActivity:
Delete
by
Age
I/com.breakloop.contentproviderdemo2.MainActivity:
delete
1
record
I/com.breakloop.contentproviderdemo2.MainActivity:
Select
All
I/com.breakloop.contentproviderdemo2.MainActivity:
name
=
C
age
=
12
Female
I/com.breakloop.contentproviderdemo2.
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年中国一次性使用手术服市场调查研究报告
- 2025年中国L-丙氨酸市场调查研究报告
- 音乐与心理状态的影响研究试题及答案
- 理解创业者政策需求试题及答案
- 2025养殖业的买卖合同模板
- 考架科目四试题及答案
- 2025年水平井、定向井、钻井装备及器具项目发展计划
- 《原理与电子电路》课件
- 2025年液晶聚合物LCP合作协议书
- 2025年滤紫外石英玻璃灯管项目发展计划
- 《隧道防火保护板系统技术规程》
- 2025年安徽黄山旅游集团招聘笔试参考题库含答案解析
- 中铜国际贸易集团有限公司招聘笔试冲刺题2025
- 商演服务合同
- 《建筑采光分析》课件
- 海洋机器人与人工智能知到智慧树章节测试课后答案2024年秋哈尔滨工程大学
- 上海市境内旅游合同 示范文本(2013版)
- 钢构制品加工协议
- “煎炒烹炸”与中药疗效(安徽中医药大学)知道智慧树章节答案
- 病毒蛋白相互作用
- 一年级数学下册100以内加减法口算题一
评论
0/150
提交评论