您的位置:首页 > 编程语言 > PHP开发

四大组件之ContentProvider(二)-轻轻松松自定义ContentProvider

2016-06-17 12:15 633 查看

第3节 自定义ContentProvider

自定义一个
ContentProvider
,需要

继承
ContentProvider类
重新创建一个类,并实现其中的一些方法;

在应用的
AndroidManifest.xml
文件中,声明这个新添加的组件;

但在这之前,我们要来设计一下外部访问它采用的地址。

3.1 地址设计

Uri
scheme
字段是固定的,使用
content:


authority
定义成程序的包名
com.anddle.mycontentprovider


path
就像是网站内部的分类,依据网站的逻辑进行划分。

假设我们的
ContentProvider
提供书籍book和文件file两种内容的查询操作。而每种类型都可以进行单一数据的操作和多条数据的操作。

例如,

操作所有书的信息:
content://com.anddle.mycontentprovider/books
;

操作某本特定书的信息:
content://com.anddle.mycontentprovider/books/8


操作所有文件的信息:
content://com.anddle.mycontentprovider/files


操作某个特定文件的信息:
content://com.anddle.mycontentprovider/files/3


所以,在对这些地址代表的对象进行增删改查的时候,就需要分析出它们针对的对象。

3.2 创建ContentProvider子类

继承
ContentProvider类
,会要求我们实现
getType()
insert()
delete()
update()
query()
onCreate()
等接口,

public class MyContentProvider extends ContentProvider {

@Override
public boolean onCreate() {

return true;
}

@Override
public String getType(Uri uri) {

throw new UnsupportedOperationException("Not yet implemented");
}

@Override
public Uri insert(Uri uri, ContentValues values) {

throw new UnsupportedOperationException("Not yet implemented");
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {

throw new UnsupportedOperationException("Not yet implemented");
}

@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {

throw new UnsupportedOperationException("Not yet implemented");
}

@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {

throw new UnsupportedOperationException("Not yet implemented");
}

}


定义提供给其他组件使用的“网络地址”URI,这里我们把它们定义成
content://com.anddle.mycontentprovider/books
content://com.anddle.mycontentprovider/files


private static final String SCHEME = "content://";

private static final String PATH_BOOKS = "/books";
private static final String PATH_FILES = "/files";

public static final String AUTHORITY = "com.anddle.mycontentprovider";

//"content://com.anddle.mycontentprovider/books"
public static final Uri CONTENT_BOOKS_URI = Uri.parse(SCHEME + AUTHORITY + PATH_BOOKS);

//"content://com.anddle.mycontentprovider/files"
public static final Uri CONTENT_FILES_URI = Uri.parse(SCHEME + AUTHORITY + PATH_FILES);


定义解析地址的匹配器,

private static final int BOOKS = 0;
private static final int BOOK = 1;
private static final int FILES = 2;
private static final int FILE = 3;

private static final UriMatcher sUriMatcher;

static {

sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

sUriMatcher.addURI(AUTHORITY, PATH_BOOKS, BOOKS);
sUriMatcher.addURI(AUTHORITY, PATH_BOOKS+"/#", BOOK);

sUriMatcher.addURI(AUTHORITY, PATH_FILES, FILES);
sUriMatcher.addURI(AUTHORITY, PATH_FILES+"/#", FILE);

}


UriMatcher
可以对传入的字符串进行匹配检测,如果匹配成功,会返回一个对应的值,例如,

int type = sUriMatcher.match("content://com.anddle.mycontentprovider/files");
//type就等于FILES的值2


type就等于FILES的值2。利用这个方法,我们就可以区分出Uri访问
ContentProvider
时,到底希望操作什么样的数据。

创建匹配器的时候,加入
sUriMatcher.addURI("content://com.anddle.mycontentprovider","files/#", FILE);
这种带有”#”的关键字段,表示如下这种匹配方式,即匹配任何数字

content://com.anddle.mycontentprovider/files/0
content://com.anddle.mycontentprovider/files/1
content://com.anddle.mycontentprovider/files/3


创建匹配器的时候,加入
sUriMatcher.addURI("content://com.anddle.mycontentprovider","files/*", FILE);
这种带有”#”的关键字段,表示如下这种匹配方式,即匹配任何字符

content://com.anddle.mycontentprovider/files/how-to-program
content://com.anddle.mycontentprovider/files/bible
content://com.anddle.mycontentprovider/files/101story


在回调函数中,根据Uri,做对应的操作,

@Override
public Uri insert(Uri uri, ContentValues values) {

Uri result = null;


switch (sUriMatcher.match(uri)) {

case BOOKS: {
//从ContentValues中取出数据,保存起来;返回保存数据的Uri地址,例如
//content://com.anddle.mycontentprovider/books
}
break;

case BOOK: {
//从ContentValues中取出数据,保存起来;返回保存数据的Uri地址,例如
//content://com.anddle.mycontentprovider/books/8
}
break;

case FILES: {
//从ContentValues中取出数据,保存起来;返回保存数据的Uri地址,例如
//content://com.anddle.mycontentprovider/files
}
break;

case FILE: {
//从ContentValues中取出数据,保存起来;返回保存数据的Uri地址,例如
//content://com.anddle.mycontentprovider/files/8
}
break;

default:
throw new IllegalArgumentException("Unknown URI " + uri);
}

return result;
}


这里就要实现对数据增删改查的真正操作。

ContentProvider
中,可以使用很多方式对数据进行保存、修改,例如SQL数据库。不过我们暂时不去实现,把它放到下一个章节专门介绍。

其他
delete()
update()
query()
实现的函数做类似处理。

对于
getType()
, 需要为每一种类型的
Uri
返回一种数据类型-
MIME type
,告诉调用者,当前这种Uri可以处理什么类型的数据。

它的格式型如
type\subtype
,有很多知名的
MIME type
类型,例如
application/pdf
image/jpeg
等等,可以在网上查找到公开的
MIME type
类型有哪些。也可以自定义自己应用支持的特殊
MIME type
类型。

这里我们就返回一个空值,

@Override
public String getType(Uri uri) {

return null;
}


至此,一个
ContentProvider
的就完成了。不过它现在还没有添加上真正可以存储数据的功能。

/[b]*******************************************************************[/b]/

版权声明

本教程只在CSDN和安豆网发布,其他网站出现本教程均为盗链。

/[b]*******************************************************************[/b]/

3.3 声明ContentProvider

千万不要忘记,在应用的
AndroidManifest.xml
文件中,声明新添加的
ContentProvider


<provider
android:name=".MyContentProvider"
android:authorities="com.anddle.mycontentprovider"
android:enabled="true"
android:exported="true" />


这里的
android:authorities
属性值,就要填写定义
MyContentProvider
时,代码中的那个,

public static final String AUTHORITY = "com.anddle.mycontentprovider";


android:exported
属性如何设置成
true
,说明这个
ContentProvider
可以被其他应用使用(就像一个公共网站,可以被任何人访问),如果设置成
false
,说明它只能被自己所在的应用使用(就像一个内部网站,只能在公司内部访问)。

3.4 使用自定义ContentProvider

无论是使用应用自己的
ContentProvider
还是使用其他应用提供的,它们的使用方式都和使用系统提供的
ContentProvider
一样,

添加一条数据数据:通过
ContentResolver
获取访问
ContentProvider
的入口,使用
ContentValues
添加要插入的数据;

ContentResolver cr = getContentResolver();
ContentValues cv = new ContentValues();
cv.put("数据字段名称", "数据内容");
Uri uri = cr.insert("content://com.anddle.mycontentprovider/books", cv)


通常会返回指向刚成功插入的这条数据的
Uri
(内容就如
content://com.anddle.mycontentprovider/books/8
)。

删除一条数据:通过
ContentResolver
获取访问
ContentProvider
的入口,使用
Uri
删除指定的数据;

String where = null;
String [] keywords = null;
ContentResolver cr = getContentResolver();
cr.delete("content://com.anddle.mycontentprovider/books/8", where, keywords);


修改一条数据:通过
ContentResolver
获取访问
ContentProvider
的入口,使用
Uri
更新指定的数据,要修改的数据放在
ContentValues
当中;

String where = null;
String [] keywords = null;
ContentResolver cr = getContentResolver();
ContentValues cv = new ContentValues();
cv.put("数据字段名称", "新数据内容",where,keywords);
cr.update("content://com.anddle.mycontentprovider/books", cv, where, keywords)


查询某一类的数据(或者特定某条数据),

Uri uri = MyContentProvider.CONTENT_BOOKS_URI;

String[] searchKey = null;
String where = null;
String [] keywords = null;
String sortOrder = null;

ContentResolver resolver = getContentResolver();
Cursor cursor = resolver.query(
uri,
searchKey,
where,
keywords,
sortOrder);

if(cursor != null)
{
while(cursor.moveToNext())
{
......
}

cursor.close();
}


注意,在删改查的操作中,还会使用诸如
where
sortOrder
keywords
searcgKey
这样的参数,它们是辅助
ContentProvider
查询特定数据时用的。

虽然
Uri
已经能定位到某条具体的数据了,但是大部分的
ContentProvider
都是通过SQL数据库来实现的真正存储,因此,在设计这些接口的时候就保留了SQL语言的一些用法,让使用者也能像直接操作SQL数据库那样灵活方便的使用
ContentProvider


假如
ContentProvider
不用SQL实现数据存储功能,而采用别的存储机制,那么这些额外的参数就可以派上别的用场或者完全用不着。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: