name="DiaryContentProvider"Android:
authorities="com.ex09_2_contentprovider.diarycontentprovider"/>,其中Android:
name为我们实现的这个contentprovider的类名;Android:
authorities为contentURI的第二部分,即授权部分,代码为:
"com.ex09_2_contentprovider.diarycontentprovider"。
5.第五步
继续来看DiaryContentProvider类的代码。
此实例的数据是存储在数据库当中,和前面章节学过的数据例子一样,此实例中我们定义了DatabaseHelper辅助类。
这个类在第8章中有详细的讲解,这里就不再进行详细说明,具体代码如下所示:
1.private static class DatabaseHelper extends SQLiteOpenHelper {
2.
3.DatabaseHelper(Context context) {
4.super(context, DATABASE_NAME, null, DATABASE_VERSION);
5.}
6.
7.@Override
8.public void onCreate(SQLiteDatabase db) {
9.db.execSQL("CREATE TABLE " + DIARY_TABLE_NAME + " ("
10.+ DiaryColumns._ID + " INTEGER PRIMARY KEY,"
11.+ DiaryColumns.TITLE + " TEXT," + DiaryColumns.BODY
12.+ " TEXT," + DiaryColumns.CREATED + " TEXT" + ");");
13.}
14.
15.@Override
16.public void onUpgrade(SQLiteDatabase db, int
oldVersion, int newVersion) {
17.db.execSQL("DROP TABLE IF EXISTS notes");
18.onCreate(db);
19.}
20.}
代码解释:
DatabaseHelper里操作数据库的辅助类,通过这个类我们可以生成数据库,并且维护这个数据库。
在DiaryContentProvider中,我们定义了一些变量和常量,其中这些常量主要是描述数据库的信息。
1.private static final String DATABASE_NAME = "database";
2.private static final int DATABASE_VERSION = 1;
3.private static final String DIARY_TABLE_NAME = "diary";
4.
5.private static HashMap sDiariesProjectionMap;
6.
7.private static final int DIARIES = 1;
8.private static final int DIARY_ID = 2;
9.
10.private static final UriMatcher sUriMatcher;
小知识 什么是UriMatcher?
UriMatcher是匹配Uri的一个辅助类,例如,在我们的DiaryContentProvider中的static模块中,有下边的代码:
sUriMatcher=newUriMatcher(UriMatcher.NO_MATCH);
sUriMatcher.addURI(Diary.AUTHORITY,"diaries",DIARIES);
sUriMatcher.addURI(Diary.AUTHORITY,"diaries/#",DIARY_ID);
代码解释:
sUriMatcher.addURI(Diary.AUTHORITY,"diaries",sUriMatcher.match(uri))表示,如果我们的Uri是content:
//com.ex09_2_contentprovider.diarycontentprovider/diaries/,那么sUriMatcher.match(uri)的返回值就是DIARIES。
sUriMatcher.addURI(Diary.AUTHORITY,"diaries/#",DIARY_ID)表示,如果我们的Uri是content:
//com.ex09_2_contentprovider.diarycontentprovider/diaries/id(其中后边的id是一个数字),那么sUriMatcher.match(uri)的返回值就是DIARY_ID。
通过UriMatcher类我们可以很方便地判断一个Uri的类型,特别是判断这个Uri是对单个数据的请求,还是对全部数据的请求。
8.5.3 使用ContentProvider操作数据日记本实例(3)
6.第六步
现在我们来看一下在第四步列出来的抽象方法具体是怎么实现的。
我们就从增、删、改、查的顺序说起。
(1)首先来看插入的方法:
insert()。
具体实现代码如下所示:
1.@Override
2.public Uri insert(Uri uri, ContentValues initialValues) {
3.if (sUriMatcher.match(uri) !
= DIARIES) {
4.throw new IllegalArgumentException("Unknown URI " + uri);
5.}
6.
7.ContentValues values;
8.if (initialValues !
= null) {
9.values = new ContentValues(initialValues);
10.} else {
11.values = new ContentValues();
12.}
13.
14.if (values.containsKey(Diary.DiaryColumns.CREATED) == false) {
15.values.put(Diary.DiaryColumns.CREATED, getFormateCreatedDate());
16.}
17.
18.if (values.containsKey(Diary.DiaryColumns.TITLE) == false) {
19.Resources r = Resources.getSystem();
20.values.put(Diary.DiaryColumns.TITLE, r
21..getString(Android.R.string.untitled));
22.}
23.
24.if (values.containsKey(Diary.DiaryColumns.BODY) == false) {
25.values.put(Diary.DiaryColumns.BODY, "");
26.}
27.
28.SQLiteDatabase db = mOpenHelper.getWritableDatabase();
29.long rowId = db.insert(DIARY_TABLE_NAME, DiaryColumns.BODY, values);
30.if (rowId > 0) {
31.Uri diaryUri= ContentUris.withAppendedId(
32.Diary.DiaryColumns.CONTENT_URI, rowId);
33.return diaryUri;
34.}
35.
36.throw new SQLException("Failed to insert row into " + uri);
37.}
代码解释:
首先我们通过语句sUriMatcher.match(uri)!
=DIARIES对传进来的Uri进行了判断,如果这个Uri不是DIARIES类型的,那么这个Uri就是一个非法的Uri。
SQLiteDatabasedb=mOpenHelper.getWritableDatabase()语句负责得到一个SQLiteDatabase的实例。
db.insert(DIARY_TABLE_NAME,DiaryColumns.BODY,values)语句负责插入一条记录到数据库中。
需要注意的是,insert()返回的是一个Uri,而不是一个记录的id,所以,我们还应该把记录的id构造成一个Uri:
UridiaryUri=ContentUris.withAppendedId(Diary.DiaryColumns.CONTENT_URI,rowId).withAppendedId()方法在下边的小知识当中详细介绍。
小知识 什么是ContentUris?
ContentUris是contentURI的一个辅助类。
它有两个方法很有用,具体如下所示。
publicstaticUriwithAppendedId(UricontentUri,longid),这个方法负责把id和contentUri连接成一个新的Uri。
比如在我们这个例子当中是这么使用的:
ContentUris.withAppendedId(Diary.DiaryColumns.CONTENT_URI,rowId)。
如果rowId为100的话,那么现在的这个Uri的内容就是:
content:
//com.ex09_2_contentprovider.diarycontentprovider/diaries/100。
publicstaticlongparseId(UricontentUri),这个方法负责把contentURI后边的id解析出来,比如现在这个contentURI是content:
//com.ex09_2_contentprovider.diarycontentprovider/diaries/100,那么这个函数的返回值就是100。
(2)现在来看删除方法:
delete()。
具体实现代码如下所示:
1.@Override
2.public int delete(Uri uri, String where, String[] whereArgs) {
3.SQLiteDatabase db = mOpenHelper.getWritableDatabase();
4.String rowId = uri.getPathSegments().get
(1);
5.return db .delete(DIARY_TABLE_NAME, DiaryColumns._ID + "=" + rowId, null);
6.}
代码解释:
rowId=uri.getPathSegments().get
(1)负责得到rowId的值。
getPathSegments()方法得到一个String的List,在我们例子当中uri.getPathSegments().get
(1)为rowId,如果是uri.getPathSegments().get(0)那值就为"diaries"。
db.delete(DIARY_TABLE_NAME,DiaryColumns._ID+"="+rowId,null)是标准的SQLite删除操作。
第一个参数数据表的名字,第二个参数相当于SQL语句当中的where部分。
(3)更新一条数据的方法:
update()。
具体实现代码如下所示:
1.@Override
2.public int update(Uri uri, ContentValues values, String where,
3.String[] whereArgs) {
4.SQLiteDatabase db = mOpenHelper.getWritableDatabase();
5.String rowId = uri.getPathSegments().get
(1);
6.return db.update(DIARY_TABLE_NAME, values, DiaryColumns._ID + "="
7.+ rowId